@tuturuuu/ui 0.32.0 → 0.33.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 +49 -0
- package/biome.json +1 -1
- package/package.json +53 -51
- package/src/components/ui/calendar-app/components/calendar-sync-attention-button.tsx +58 -24
- package/src/components/ui/calendar-app/components/calendar-sync-recovery.test.tsx +57 -0
- package/src/components/ui/calendar-app/components/calendar-sync-recovery.tsx +28 -14
- package/src/components/ui/calendar-app/components/refresh-calendar-sync-status.test.tsx +321 -0
- package/src/components/ui/calendar-app/components/refresh-calendar-sync-status.ts +182 -0
- package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +12 -14
- package/src/components/ui/chat/ai-message-parts.test.tsx +47 -0
- package/src/components/ui/chat/ai-message-parts.tsx +23 -16
- package/src/components/ui/chat/ai-message-render-utils.ts +19 -1
- package/src/components/ui/commercial-comparison-style.ts +104 -0
- package/src/components/ui/commercial-comparison-table.tsx +159 -0
- package/src/components/ui/commercial-comparison-toolbar.tsx +205 -0
- package/src/components/ui/commercial-comparison.test.tsx +86 -0
- package/src/components/ui/commercial-comparison.tsx +224 -0
- package/src/components/ui/comparison-value.test.tsx +32 -0
- package/src/components/ui/comparison-value.tsx +72 -0
- package/src/components/ui/custom/__tests__/report-preview-pagination-progress.test.ts +129 -0
- package/src/components/ui/custom/__tests__/report-preview-viewport.test.tsx +56 -0
- package/src/components/ui/custom/education/modules/resources/pdf-viewer.tsx +13 -2
- package/src/components/ui/custom/report-preview-pagination.ts +5 -3
- package/src/components/ui/custom/report-preview-viewport.tsx +40 -0
- package/src/components/ui/custom/report-preview.tsx +2 -3
- package/src/components/ui/finance/categories-tags-tabs.tsx +3 -0
- package/src/components/ui/finance/invoices/columns.tsx +2 -0
- package/src/components/ui/finance/invoices/components/invoice-checkout-summary.tsx +6 -3
- package/src/components/ui/finance/invoices/components/invoice-data-state.test.tsx +27 -0
- package/src/components/ui/finance/invoices/components/invoice-data-state.tsx +34 -0
- package/src/components/ui/finance/invoices/hooks/use-invoice-customer-search.test.tsx +89 -0
- package/src/components/ui/finance/invoices/hooks/use-invoice-customer-search.ts +117 -0
- package/src/components/ui/finance/invoices/hooks.ts +5 -110
- package/src/components/ui/finance/invoices/internal-api.test.ts +122 -0
- package/src/components/ui/finance/invoices/internal-api.ts +19 -1
- package/src/components/ui/finance/invoices/invoice-discount.test.tsx +107 -0
- package/src/components/ui/finance/invoices/invoice-discount.ts +12 -0
- package/src/components/ui/finance/invoices/invoice-history-filters.tsx +121 -0
- package/src/components/ui/finance/invoices/invoice-history-pagination.tsx +81 -0
- package/src/components/ui/finance/invoices/invoice-history-row.tsx +159 -0
- package/src/components/ui/finance/invoices/invoice-history.test.tsx +170 -0
- package/src/components/ui/finance/invoices/invoice-history.tsx +300 -0
- package/src/components/ui/finance/invoices/invoice-page.tsx +18 -2
- package/src/components/ui/finance/invoices/invoiceId/full-invoice-template.tsx +3 -7
- package/src/components/ui/finance/invoices/invoiceId/invoice-details-page.test.tsx +16 -0
- package/src/components/ui/finance/invoices/invoiceId/invoice-details-page.tsx +9 -0
- package/src/components/ui/finance/invoices/invoices-table.tsx +3 -0
- package/src/components/ui/finance/invoices/promotion-form.tsx +5 -4
- package/src/components/ui/finance/invoices/query-invalidation.ts +1 -0
- package/src/components/ui/finance/invoices/row-actions.tsx +35 -4
- package/src/components/ui/finance/invoices/standard-invoice.tsx +27 -16
- package/src/components/ui/finance/invoices/subscription-invoice-props.ts +20 -0
- package/src/components/ui/finance/invoices/subscription-invoice.test.tsx +71 -4
- package/src/components/ui/finance/invoices/subscription-invoice.tsx +44 -45
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-body.tsx +73 -80
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-controls.tsx +3 -1
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-legend.test.tsx +30 -0
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-legend.tsx +31 -24
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-tooltip.tsx +9 -6
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-types.ts +2 -0
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-utils.test.ts +59 -0
- package/src/components/ui/finance/shared/charts/category-breakdown-chart-utils.ts +51 -37
- package/src/components/ui/finance/shared/charts/category-breakdown-chart.tsx +37 -7
- package/src/components/ui/public-workspace-prices.tsx +13 -0
- package/src/components/ui/pwa-status.test.tsx +13 -2
- package/src/components/ui/pwa-status.tsx +15 -3
- package/src/components/ui/text-editor/editor-readonly-transition.test.tsx +86 -0
- package/src/components/ui/text-editor/editor.tsx +11 -3
- package/src/components/ui/text-editor/task-item-checkbox-view.test.tsx +188 -65
- package/src/components/ui/text-editor/task-item-checkbox-view.tsx +178 -164
- package/src/components/ui/text-editor/task-item-status-picker.tsx +130 -0
- package/src/hooks/__tests__/use-calendar-sync.test.tsx +20 -1
- package/src/hooks/__tests__/use-notifications-subscription.test.tsx +99 -180
- package/src/hooks/calendar-provider-sync.ts +33 -0
- package/src/hooks/notification-subscription.ts +74 -0
- package/src/hooks/use-calendar-sync.tsx +11 -14
- package/src/hooks/use-calendar.tsx +2 -2
- package/src/hooks/use-notifications.ts +5 -141
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type QueryClient,
|
|
3
2
|
useInfiniteQuery,
|
|
4
3
|
useMutation,
|
|
5
4
|
useQuery,
|
|
6
5
|
useQueryClient,
|
|
7
6
|
} from '@tanstack/react-query';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from '
|
|
13
|
-
import { useEffect } from 'react';
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
__resetNotificationSubscriptionRegistryForTests,
|
|
10
|
+
useNotificationSubscription,
|
|
11
|
+
} from './notification-subscription';
|
|
14
12
|
export type NotificationType =
|
|
15
13
|
| 'task_assigned'
|
|
16
14
|
| 'task_updated'
|
|
@@ -78,98 +76,8 @@ interface UseNotificationsOptions {
|
|
|
78
76
|
readOnly?: boolean;
|
|
79
77
|
type?: NotificationType;
|
|
80
78
|
}
|
|
81
|
-
interface NotificationSubscriptionEntry {
|
|
82
|
-
channel: RealtimeChannel;
|
|
83
|
-
queryClientRefs: Map<QueryClient, number>;
|
|
84
|
-
subscriberCount: number;
|
|
85
|
-
supabase: SupabaseClient;
|
|
86
|
-
}
|
|
87
79
|
export const UNREAD_COUNT_STALE_TIME_MS = 5 * 60 * 1000;
|
|
88
80
|
export const UNREAD_COUNT_FALLBACK_INTERVAL_MS = 15 * 60 * 1000;
|
|
89
|
-
const notificationSubscriptionRegistry = new Map<
|
|
90
|
-
string,
|
|
91
|
-
NotificationSubscriptionEntry
|
|
92
|
-
>();
|
|
93
|
-
function invalidateNotificationQueries(
|
|
94
|
-
queryClientRefs: Map<QueryClient, number>
|
|
95
|
-
) {
|
|
96
|
-
for (const queryClient of queryClientRefs.keys()) {
|
|
97
|
-
queryClient.invalidateQueries({ queryKey: ['notifications'] });
|
|
98
|
-
queryClient.invalidateQueries({
|
|
99
|
-
queryKey: ['notifications', 'unread-count'],
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function addNotificationQueryClientRef(
|
|
104
|
-
entry: NotificationSubscriptionEntry,
|
|
105
|
-
queryClient: QueryClient
|
|
106
|
-
) {
|
|
107
|
-
entry.subscriberCount += 1;
|
|
108
|
-
entry.queryClientRefs.set(
|
|
109
|
-
queryClient,
|
|
110
|
-
(entry.queryClientRefs.get(queryClient) ?? 0) + 1
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
function releaseNotificationQueryClientRef(
|
|
114
|
-
entry: NotificationSubscriptionEntry,
|
|
115
|
-
queryClient: QueryClient
|
|
116
|
-
) {
|
|
117
|
-
entry.subscriberCount -= 1;
|
|
118
|
-
const currentRefCount = entry.queryClientRefs.get(queryClient) ?? 0;
|
|
119
|
-
if (currentRefCount <= 1) {
|
|
120
|
-
entry.queryClientRefs.delete(queryClient);
|
|
121
|
-
} else {
|
|
122
|
-
entry.queryClientRefs.set(queryClient, currentRefCount - 1);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function createNotificationSubscriptionEntry(
|
|
126
|
-
userId: string,
|
|
127
|
-
queryClient: QueryClient
|
|
128
|
-
) {
|
|
129
|
-
const queryClientRefs = new Map<QueryClient, number>([[queryClient, 1]]);
|
|
130
|
-
const supabase = createRealtimeClient();
|
|
131
|
-
const invalidateQueries = () =>
|
|
132
|
-
invalidateNotificationQueries(queryClientRefs);
|
|
133
|
-
const channel = supabase
|
|
134
|
-
.channel(`notifications-${userId}`)
|
|
135
|
-
.on(
|
|
136
|
-
'postgres_changes',
|
|
137
|
-
{
|
|
138
|
-
event: 'INSERT',
|
|
139
|
-
schema: 'public',
|
|
140
|
-
table: 'notifications',
|
|
141
|
-
filter: `user_id=eq.${userId}`,
|
|
142
|
-
},
|
|
143
|
-
invalidateQueries
|
|
144
|
-
)
|
|
145
|
-
.on(
|
|
146
|
-
'postgres_changes',
|
|
147
|
-
{
|
|
148
|
-
event: 'UPDATE',
|
|
149
|
-
schema: 'public',
|
|
150
|
-
table: 'notifications',
|
|
151
|
-
filter: `user_id=eq.${userId}`,
|
|
152
|
-
},
|
|
153
|
-
invalidateQueries
|
|
154
|
-
)
|
|
155
|
-
.on(
|
|
156
|
-
'postgres_changes',
|
|
157
|
-
{
|
|
158
|
-
event: 'DELETE',
|
|
159
|
-
schema: 'public',
|
|
160
|
-
table: 'notifications',
|
|
161
|
-
filter: `user_id=eq.${userId}`,
|
|
162
|
-
},
|
|
163
|
-
invalidateQueries
|
|
164
|
-
)
|
|
165
|
-
.subscribe();
|
|
166
|
-
return {
|
|
167
|
-
channel,
|
|
168
|
-
queryClientRefs,
|
|
169
|
-
subscriberCount: 1,
|
|
170
|
-
supabase,
|
|
171
|
-
} satisfies NotificationSubscriptionEntry;
|
|
172
|
-
}
|
|
173
81
|
export function dedupeNotifications(
|
|
174
82
|
notifications: Notification[]
|
|
175
83
|
): Notification[] {
|
|
@@ -665,47 +573,3 @@ export function useDeleteNotification() {
|
|
|
665
573
|
},
|
|
666
574
|
});
|
|
667
575
|
}
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* Hook to subscribe to realtime notification updates
|
|
671
|
-
* Subscribes to all notifications for the user, regardless of workspace
|
|
672
|
-
*/
|
|
673
|
-
export function useNotificationSubscription(
|
|
674
|
-
_wsId: string | null,
|
|
675
|
-
userId: string
|
|
676
|
-
) {
|
|
677
|
-
const queryClient = useQueryClient();
|
|
678
|
-
|
|
679
|
-
useEffect(() => {
|
|
680
|
-
if (!userId) return;
|
|
681
|
-
|
|
682
|
-
const registryKey = userId;
|
|
683
|
-
let entry = notificationSubscriptionRegistry.get(registryKey);
|
|
684
|
-
|
|
685
|
-
if (entry) {
|
|
686
|
-
addNotificationQueryClientRef(entry, queryClient);
|
|
687
|
-
} else {
|
|
688
|
-
entry = createNotificationSubscriptionEntry(userId, queryClient);
|
|
689
|
-
notificationSubscriptionRegistry.set(registryKey, entry);
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
return () => {
|
|
693
|
-
if (!entry) return;
|
|
694
|
-
|
|
695
|
-
releaseNotificationQueryClientRef(entry, queryClient);
|
|
696
|
-
|
|
697
|
-
if (entry.subscriberCount <= 0) {
|
|
698
|
-
notificationSubscriptionRegistry.delete(registryKey);
|
|
699
|
-
entry.supabase.removeChannel(entry.channel);
|
|
700
|
-
}
|
|
701
|
-
};
|
|
702
|
-
}, [userId, queryClient]);
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
export function __resetNotificationSubscriptionRegistryForTests() {
|
|
706
|
-
for (const entry of notificationSubscriptionRegistry.values()) {
|
|
707
|
-
entry.supabase.removeChannel(entry.channel);
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
notificationSubscriptionRegistry.clear();
|
|
711
|
-
}
|