@tuturuuu/ui 0.8.0 → 0.9.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 +40 -0
- package/biome.json +1 -1
- package/package.json +73 -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-shell.test.tsx +3 -0
- package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +19 -0
- 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/settings-dialog-shell.tsx +2 -1
- package/src/components/ui/custom/theme-toggle.tsx +1 -1
- package/src/components/ui/custom/workspace-select.tsx +8 -3
- 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 +270 -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 +222 -109
- package/src/components/ui/tu-do/boards/boardId/board-column.tsx +112 -43
- 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/data/kanban-deadline-query.ts +50 -2
- 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/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 +397 -2
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +103 -13
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-deadline-panels.tsx +443 -19
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-skeleton.tsx +94 -32
- package/src/components/ui/tu-do/boards/boardId/kanban.tsx +213 -106
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +26 -4
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +5 -2
- package/src/components/ui/tu-do/boards/boardId/task-card/measured-task-card.tsx +3 -0
- 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.tsx +191 -28
- 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 +7 -0
- 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/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/shared/__tests__/board-client.test.tsx +25 -0
- package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +341 -38
- package/src/components/ui/tu-do/shared/__tests__/board-switcher.test.tsx +253 -0
- package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +203 -2
- package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +17 -0
- package/src/components/ui/tu-do/shared/__tests__/task-legacy-route-recovery.test.tsx +16 -0
- package/src/components/ui/tu-do/shared/board-client.tsx +2 -7
- package/src/components/ui/tu-do/shared/board-config-storage.ts +7 -1
- package/src/components/ui/tu-do/shared/board-header.tsx +464 -975
- package/src/components/ui/tu-do/shared/board-layout-settings.tsx +165 -136
- package/src/components/ui/tu-do/shared/board-switcher.tsx +209 -217
- package/src/components/ui/tu-do/shared/board-views.tsx +587 -75
- package/src/components/ui/tu-do/shared/list-view.tsx +227 -1
- 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-edit-dialog/field-diff-viewer.tsx +3 -2
- 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-snapshot-dialog.tsx +8 -3
- package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +2 -1
- package/src/components/ui/tu-do/shared/task-legacy-route-recovery.tsx +2 -9
- 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/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/useBoardRealtimeEventHandler.ts +11 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { Dialog, DialogContent, DialogTitle } from './dialog';
|
|
6
|
+
|
|
7
|
+
function renderOpenDialog(children: ReactNode) {
|
|
8
|
+
return render(<Dialog open>{children}</Dialog>);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe('DialogContent presentation', () => {
|
|
12
|
+
it('keeps the default centered dialog animation classes', () => {
|
|
13
|
+
renderOpenDialog(
|
|
14
|
+
<DialogContent>
|
|
15
|
+
<DialogTitle>Default dialog</DialogTitle>
|
|
16
|
+
</DialogContent>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const dialog = screen.getByRole('dialog', { name: 'Default dialog' });
|
|
20
|
+
const className = dialog.getAttribute('class') ?? '';
|
|
21
|
+
|
|
22
|
+
expect(className).toContain('top-[50%]');
|
|
23
|
+
expect(className).toContain('left-[50%]');
|
|
24
|
+
expect(className).toContain('data-[state=open]:animate-in');
|
|
25
|
+
expect(className).toContain('data-[state=open]:fade-in-0');
|
|
26
|
+
expect(className).toContain('data-[state=open]:zoom-in-95');
|
|
27
|
+
expect(dialog).toHaveClass('rounded-lg');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders fullscreen content as an opaque non-animated viewport surface', () => {
|
|
31
|
+
renderOpenDialog(
|
|
32
|
+
<DialogContent presentation="fullscreen">
|
|
33
|
+
<DialogTitle>Fullscreen dialog</DialogTitle>
|
|
34
|
+
</DialogContent>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const dialog = screen.getByRole('dialog', { name: 'Fullscreen dialog' });
|
|
38
|
+
const className = dialog.getAttribute('class') ?? '';
|
|
39
|
+
|
|
40
|
+
expect(dialog).toHaveClass('fixed');
|
|
41
|
+
expect(dialog).toHaveClass('inset-0');
|
|
42
|
+
expect(dialog).toHaveClass('h-dvh');
|
|
43
|
+
expect(dialog).toHaveClass('max-h-dvh');
|
|
44
|
+
expect(dialog).toHaveClass('w-screen');
|
|
45
|
+
expect(dialog).toHaveClass('max-w-none');
|
|
46
|
+
expect(dialog).toHaveClass('bg-background');
|
|
47
|
+
expect(dialog).toHaveClass('rounded-none');
|
|
48
|
+
expect(dialog).toHaveClass('border-0');
|
|
49
|
+
expect(dialog).toHaveClass('shadow-none');
|
|
50
|
+
expect(className).not.toMatch(/animate-in|fade-in|zoom-in|slide-in/);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
4
|
-
import { XIcon } from '@tuturuuu/icons';
|
|
4
|
+
import { XIcon } from '@tuturuuu/icons/lucide-static';
|
|
5
5
|
import { cn } from '@tuturuuu/utils/format';
|
|
6
6
|
import type * as React from 'react';
|
|
7
7
|
|
|
@@ -51,9 +51,11 @@ function DialogContent({
|
|
|
51
51
|
children,
|
|
52
52
|
role = 'dialog',
|
|
53
53
|
showCloseButton = true,
|
|
54
|
+
presentation = 'default',
|
|
54
55
|
...props
|
|
55
56
|
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
56
57
|
showCloseButton?: boolean;
|
|
58
|
+
presentation?: 'default' | 'fullscreen';
|
|
57
59
|
}) {
|
|
58
60
|
return (
|
|
59
61
|
<DialogPortal data-slot="dialog-portal">
|
|
@@ -62,7 +64,9 @@ function DialogContent({
|
|
|
62
64
|
data-slot="dialog-content"
|
|
63
65
|
role={role}
|
|
64
66
|
className={cn(
|
|
65
|
-
|
|
67
|
+
presentation === 'fullscreen'
|
|
68
|
+
? 'fixed inset-0 z-50 flex h-dvh max-h-dvh w-screen max-w-none gap-0 overflow-hidden rounded-none border-0 bg-background p-0 shadow-none'
|
|
69
|
+
: 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg',
|
|
66
70
|
className
|
|
67
71
|
)}
|
|
68
72
|
onClick={(e) => e.stopPropagation()}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CheckIcon,
|
|
6
|
+
ChevronRightIcon,
|
|
7
|
+
CircleIcon,
|
|
8
|
+
} from '@tuturuuu/icons/lucide-static';
|
|
5
9
|
import { cn } from '@tuturuuu/utils/format';
|
|
6
10
|
import type * as React from 'react';
|
|
7
11
|
|
|
@@ -9,6 +9,10 @@ import type {
|
|
|
9
9
|
InterestCalculationType,
|
|
10
10
|
} from '@tuturuuu/types/primitives/DebtLoan';
|
|
11
11
|
import type { Wallet } from '@tuturuuu/types/primitives/Wallet';
|
|
12
|
+
import {
|
|
13
|
+
resolveSupportedCurrency,
|
|
14
|
+
SUPPORTED_CURRENCIES,
|
|
15
|
+
} from '@tuturuuu/utils/currencies';
|
|
12
16
|
import { useTranslations } from 'next-intl';
|
|
13
17
|
import { useCallback, useState } from 'react';
|
|
14
18
|
import { useForm } from 'react-hook-form';
|
|
@@ -36,6 +40,7 @@ interface Props {
|
|
|
36
40
|
data?: DebtLoan;
|
|
37
41
|
wallets?: Wallet[];
|
|
38
42
|
defaultType?: DebtLoanType;
|
|
43
|
+
defaultCurrency?: string;
|
|
39
44
|
onFinish?: (data: DebtLoanFormData) => void;
|
|
40
45
|
onCancel?: () => void;
|
|
41
46
|
}
|
|
@@ -45,12 +50,14 @@ export function DebtLoanForm({
|
|
|
45
50
|
data,
|
|
46
51
|
wallets = [],
|
|
47
52
|
defaultType = 'debt',
|
|
53
|
+
defaultCurrency,
|
|
48
54
|
onFinish,
|
|
49
55
|
onCancel,
|
|
50
56
|
}: Props) {
|
|
51
57
|
const t = useTranslations('ws-debt-loan');
|
|
52
58
|
const [loading, setLoading] = useState(false);
|
|
53
59
|
const formSchema = createDebtLoanFormSchema(t);
|
|
60
|
+
const workspaceCurrency = resolveSupportedCurrency(defaultCurrency);
|
|
54
61
|
|
|
55
62
|
const form = useForm<DebtLoanFormValues>({
|
|
56
63
|
resolver: zodResolver(formSchema),
|
|
@@ -60,7 +67,7 @@ export function DebtLoanForm({
|
|
|
60
67
|
counterparty: data?.counterparty || '',
|
|
61
68
|
type: (data?.type || defaultType) as DebtLoanType,
|
|
62
69
|
principal_amount: data?.principal_amount || 0,
|
|
63
|
-
currency: data?.currency ||
|
|
70
|
+
currency: data?.currency || workspaceCurrency,
|
|
64
71
|
interest_rate: data?.interest_rate ?? undefined,
|
|
65
72
|
interest_type: (data?.interest_type || undefined) as
|
|
66
73
|
| InterestCalculationType
|
|
@@ -226,10 +233,10 @@ export function DebtLoanForm({
|
|
|
226
233
|
<SelectField
|
|
227
234
|
id="currency"
|
|
228
235
|
placeholder={t('select_currency')}
|
|
229
|
-
options={
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
236
|
+
options={SUPPORTED_CURRENCIES.map((currency) => ({
|
|
237
|
+
value: currency.code,
|
|
238
|
+
label: `${currency.code} - ${currency.name}`,
|
|
239
|
+
}))}
|
|
233
240
|
classNames={{ selectTrigger: 'w-full' }}
|
|
234
241
|
value={field.value}
|
|
235
242
|
onValueChange={field.onChange}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
TrendingUp,
|
|
9
9
|
} from '@tuturuuu/icons';
|
|
10
10
|
import type { DebtLoanSummary } from '@tuturuuu/types/primitives/DebtLoan';
|
|
11
|
+
import { getCurrencyLocale } from '@tuturuuu/utils/currencies';
|
|
11
12
|
import { cn } from '@tuturuuu/utils/format';
|
|
12
13
|
import { useTranslations } from 'next-intl';
|
|
13
14
|
import { useFinanceHref } from '../finance-route-context';
|
|
@@ -22,8 +23,8 @@ interface Props {
|
|
|
22
23
|
|
|
23
24
|
export function DebtLoanSummaryCards({
|
|
24
25
|
summary,
|
|
25
|
-
currency = '
|
|
26
|
-
locale =
|
|
26
|
+
currency = 'USD',
|
|
27
|
+
locale = getCurrencyLocale(currency),
|
|
27
28
|
wsId,
|
|
28
29
|
}: Props) {
|
|
29
30
|
const t = useTranslations('ws-debt-loan');
|
|
@@ -5,6 +5,8 @@ import { DebtsPage } from './debts-page';
|
|
|
5
5
|
|
|
6
6
|
const mocks = vi.hoisted(() => ({
|
|
7
7
|
debtLoanForm: vi.fn(),
|
|
8
|
+
debtLoanList: vi.fn(),
|
|
9
|
+
debtLoanSummaryCards: vi.fn(),
|
|
8
10
|
getDebtLoanSummary: vi.fn(),
|
|
9
11
|
listDebtLoans: vi.fn(),
|
|
10
12
|
listWallets: vi.fn(),
|
|
@@ -31,15 +33,22 @@ vi.mock('./debt-loan-form', () => ({
|
|
|
31
33
|
}));
|
|
32
34
|
|
|
33
35
|
vi.mock('./debt-loan-list', () => ({
|
|
34
|
-
DebtLoanList: () =>
|
|
36
|
+
DebtLoanList: (props: unknown) => {
|
|
37
|
+
mocks.debtLoanList(props);
|
|
38
|
+
return null;
|
|
39
|
+
},
|
|
35
40
|
}));
|
|
36
41
|
|
|
37
42
|
vi.mock('./debt-loan-summary', () => ({
|
|
38
|
-
DebtLoanSummaryCards: () =>
|
|
43
|
+
DebtLoanSummaryCards: (props: unknown) => {
|
|
44
|
+
mocks.debtLoanSummaryCards(props);
|
|
45
|
+
return null;
|
|
46
|
+
},
|
|
39
47
|
}));
|
|
40
48
|
|
|
41
49
|
function renderDebtsPage(
|
|
42
|
-
searchParams: { create?: string; type?: string } = {}
|
|
50
|
+
searchParams: { create?: string; type?: string } = {},
|
|
51
|
+
props: { currency?: string } = {}
|
|
43
52
|
) {
|
|
44
53
|
const queryClient = new QueryClient({
|
|
45
54
|
defaultOptions: {
|
|
@@ -51,7 +60,11 @@ function renderDebtsPage(
|
|
|
51
60
|
|
|
52
61
|
return render(
|
|
53
62
|
<QueryClientProvider client={queryClient}>
|
|
54
|
-
<DebtsPage
|
|
63
|
+
<DebtsPage
|
|
64
|
+
wsId="ws-1"
|
|
65
|
+
searchParams={searchParams}
|
|
66
|
+
currency={props.currency}
|
|
67
|
+
/>
|
|
55
68
|
</QueryClientProvider>
|
|
56
69
|
);
|
|
57
70
|
}
|
|
@@ -83,15 +96,51 @@ describe('debts page', () => {
|
|
|
83
96
|
});
|
|
84
97
|
|
|
85
98
|
it('opens the loan create dialog from query state', async () => {
|
|
86
|
-
renderDebtsPage({ create: 'loan' });
|
|
99
|
+
renderDebtsPage({ create: 'loan' }, { currency: 'SGD' });
|
|
87
100
|
|
|
88
101
|
await waitFor(() => {
|
|
89
102
|
expect(mocks.debtLoanForm).toHaveBeenCalledWith(
|
|
90
103
|
expect.objectContaining({
|
|
104
|
+
defaultCurrency: 'SGD',
|
|
91
105
|
defaultType: 'loan',
|
|
92
106
|
wsId: 'ws-1',
|
|
93
107
|
})
|
|
94
108
|
);
|
|
95
109
|
});
|
|
96
110
|
});
|
|
111
|
+
|
|
112
|
+
it('passes workspace currency to summary without overriding list row currencies', async () => {
|
|
113
|
+
mocks.listDebtLoans.mockResolvedValueOnce([
|
|
114
|
+
{
|
|
115
|
+
currency: 'USD',
|
|
116
|
+
id: 'debt-1',
|
|
117
|
+
name: 'USD Debt',
|
|
118
|
+
status: 'active',
|
|
119
|
+
type: 'debt',
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
renderDebtsPage({}, { currency: 'SGD' });
|
|
124
|
+
|
|
125
|
+
await waitFor(() => {
|
|
126
|
+
expect(mocks.debtLoanSummaryCards).toHaveBeenCalledWith(
|
|
127
|
+
expect.objectContaining({
|
|
128
|
+
currency: 'SGD',
|
|
129
|
+
locale: 'en-SG',
|
|
130
|
+
})
|
|
131
|
+
);
|
|
132
|
+
expect(mocks.debtLoanList).toHaveBeenCalledWith(
|
|
133
|
+
expect.not.objectContaining({
|
|
134
|
+
currency: expect.anything(),
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
expect(mocks.debtLoanList).toHaveBeenCalledWith(
|
|
138
|
+
expect.objectContaining({
|
|
139
|
+
debtLoans: expect.arrayContaining([
|
|
140
|
+
expect.objectContaining({ currency: 'USD' }),
|
|
141
|
+
]),
|
|
142
|
+
})
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
97
146
|
});
|
|
@@ -13,6 +13,10 @@ import type {
|
|
|
13
13
|
DebtLoanWithBalance,
|
|
14
14
|
} from '@tuturuuu/types/primitives/DebtLoan';
|
|
15
15
|
import type { Wallet } from '@tuturuuu/types/primitives/Wallet';
|
|
16
|
+
import {
|
|
17
|
+
getCurrencyLocale,
|
|
18
|
+
resolveSupportedCurrency,
|
|
19
|
+
} from '@tuturuuu/utils/currencies';
|
|
16
20
|
import { useTranslations } from 'next-intl';
|
|
17
21
|
import { useEffect, useState } from 'react';
|
|
18
22
|
import { Button } from '../../button';
|
|
@@ -37,11 +41,14 @@ interface Props {
|
|
|
37
41
|
create?: string;
|
|
38
42
|
type?: string;
|
|
39
43
|
};
|
|
44
|
+
currency?: string;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
export function DebtsPage({ wsId, searchParams }: Props) {
|
|
47
|
+
export function DebtsPage({ wsId, searchParams, currency }: Props) {
|
|
43
48
|
const t = useTranslations('ws-debt-loan');
|
|
44
49
|
const queryClient = useQueryClient();
|
|
50
|
+
const workspaceCurrency = resolveSupportedCurrency(currency);
|
|
51
|
+
const workspaceCurrencyLocale = getCurrencyLocale(workspaceCurrency);
|
|
45
52
|
const requestedCreateType =
|
|
46
53
|
searchParams?.create === 'loan'
|
|
47
54
|
? 'loan'
|
|
@@ -135,7 +142,12 @@ export function DebtsPage({ wsId, searchParams }: Props) {
|
|
|
135
142
|
))}
|
|
136
143
|
</div>
|
|
137
144
|
) : summary ? (
|
|
138
|
-
<DebtLoanSummaryCards
|
|
145
|
+
<DebtLoanSummaryCards
|
|
146
|
+
summary={summary}
|
|
147
|
+
wsId={wsId}
|
|
148
|
+
currency={workspaceCurrency}
|
|
149
|
+
locale={workspaceCurrencyLocale}
|
|
150
|
+
/>
|
|
139
151
|
) : null}
|
|
140
152
|
|
|
141
153
|
<Separator />
|
|
@@ -220,6 +232,7 @@ export function DebtsPage({ wsId, searchParams }: Props) {
|
|
|
220
232
|
wsId={wsId}
|
|
221
233
|
wallets={wallets}
|
|
222
234
|
defaultType={defaultCreateType}
|
|
235
|
+
defaultCurrency={workspaceCurrency}
|
|
223
236
|
onFinish={handleFormFinish}
|
|
224
237
|
onCancel={() => setIsCreateDialogOpen(false)}
|
|
225
238
|
/>
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
ChevronDown,
|
|
7
7
|
Loader2,
|
|
8
8
|
} from '@tuturuuu/icons';
|
|
9
|
-
import type { Database } from '@tuturuuu/types';
|
|
10
9
|
import {
|
|
11
10
|
Card,
|
|
12
11
|
CardContent,
|
|
@@ -29,6 +28,7 @@ import {
|
|
|
29
28
|
getSubscriptionCoverageInvoiceForGroup,
|
|
30
29
|
isSubscriptionMonthPaidForGroup,
|
|
31
30
|
parseLocalCalendarDate,
|
|
31
|
+
type WorkspaceUserGroup,
|
|
32
32
|
} from '../utils';
|
|
33
33
|
|
|
34
34
|
type LatestInvoice = {
|
|
@@ -38,9 +38,7 @@ type LatestInvoice = {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
type UserGroupItem = {
|
|
41
|
-
workspace_user_groups:
|
|
42
|
-
| Database['public']['Tables']['workspace_user_groups']['Row']
|
|
43
|
-
| null;
|
|
41
|
+
workspace_user_groups: WorkspaceUserGroup | null;
|
|
44
42
|
};
|
|
45
43
|
|
|
46
44
|
function hasSchedule(group: UserGroupItem['workspace_user_groups']): boolean {
|
|
@@ -84,7 +82,7 @@ function GroupRow({
|
|
|
84
82
|
onToggle,
|
|
85
83
|
t,
|
|
86
84
|
}: {
|
|
87
|
-
group:
|
|
85
|
+
group: WorkspaceUserGroup;
|
|
88
86
|
isSelected: boolean;
|
|
89
87
|
isMonthPaid: boolean;
|
|
90
88
|
latestInvoice: LatestInvoice | undefined;
|
|
@@ -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
|
/>
|