@tuturuuu/ui 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/biome.json +1 -1
  3. package/package.json +62 -62
  4. package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +12 -0
  5. package/src/components/ui/custom/__tests__/sidebar-context.test.tsx +93 -6
  6. package/src/components/ui/custom/loading-statistic-card.tsx +18 -0
  7. package/src/components/ui/custom/notification-popover-client.tsx +5 -1
  8. package/src/components/ui/custom/settings/keyboard-shortcuts-settings.test.tsx +34 -0
  9. package/src/components/ui/custom/settings/keyboard-shortcuts-settings.tsx +106 -0
  10. package/src/components/ui/custom/settings/sidebar-settings.tsx +18 -6
  11. package/src/components/ui/custom/settings-dialog-shell.tsx +18 -12
  12. package/src/components/ui/custom/sidebar-context.tsx +58 -3
  13. package/src/components/ui/custom/sidebar-remote-behavior-bridge.tsx +5 -3
  14. package/src/components/ui/custom/statistic-card.tsx +104 -0
  15. package/src/components/ui/custom/structure.test.tsx +29 -0
  16. package/src/components/ui/custom/structure.tsx +103 -88
  17. package/src/components/ui/finance/invoices/civil-month.ts +224 -0
  18. package/src/components/ui/finance/invoices/components/subscription-invoice-proposal.test.tsx +49 -0
  19. package/src/components/ui/finance/invoices/components/subscription-invoice-proposal.tsx +81 -0
  20. package/src/components/ui/finance/invoices/hooks/use-subscription-auto-selection.ts +8 -2
  21. package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +90 -2
  22. package/src/components/ui/finance/invoices/new-invoice-page.tsx +40 -4
  23. package/src/components/ui/finance/invoices/pending-columns.test.ts +26 -0
  24. package/src/components/ui/finance/invoices/pending-columns.tsx +45 -14
  25. package/src/components/ui/finance/invoices/standard-invoice.test.ts +31 -0
  26. package/src/components/ui/finance/invoices/standard-invoice.tsx +33 -16
  27. package/src/components/ui/finance/invoices/subscription-invoice.test.tsx +331 -0
  28. package/src/components/ui/finance/invoices/subscription-invoice.tsx +53 -28
  29. package/src/components/ui/finance/invoices/utils.test.ts +84 -0
  30. package/src/components/ui/finance/invoices/utils.ts +56 -134
  31. package/src/components/ui/resizable.test.ts +15 -0
  32. package/src/components/ui/resizable.tsx +28 -6
  33. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/__tests__/bulk-mutations-move.test.tsx +62 -0
  34. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.test.ts +48 -0
  35. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +32 -2
  36. package/src/components/ui/tu-do/boards/boardId/menus/__tests__/task-menus.test.tsx +41 -3
  37. package/src/components/ui/tu-do/boards/boardId/menus/task-due-date-menu.tsx +31 -10
  38. package/src/components/ui/tu-do/boards/boardId/menus/task-priority-menu.tsx +7 -5
  39. package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-menu.tsx +7 -5
  40. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-archive-visibility.test.ts +44 -0
  41. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-archive-visibility.ts +17 -0
  42. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +2 -0
  43. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +7 -0
  44. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +44 -30
  45. package/src/components/ui/tu-do/my-tasks/__tests__/use-task-context-actions.test.ts +54 -0
  46. package/src/components/ui/tu-do/my-tasks/task-list-with-completion.tsx +43 -1
  47. package/src/components/ui/tu-do/my-tasks/use-task-context-actions.ts +33 -15
  48. package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +3 -3
  49. package/src/components/ui/tu-do/progress/task-progress-page.tsx +74 -28
  50. package/src/components/ui/tu-do/progress/task-progress-panels.tsx +12 -10
  51. package/src/components/ui/tu-do/projects/components/project-grid-card.tsx +22 -6
  52. package/src/components/ui/tu-do/projects/components/project-list-item.tsx +24 -8
  53. package/src/components/ui/tu-do/projects/projectId/components/__tests__/tasks-tab-layout.test.tsx +6 -0
  54. package/src/components/ui/tu-do/projects/projectId/components/tasks-tab.tsx +3 -1
  55. package/src/components/ui/tu-do/projects/projectId/task-project-detail-page-client.tsx +11 -3
  56. package/src/components/ui/tu-do/projects/projectId/task-project-detail.tsx +2 -0
  57. package/src/components/ui/tu-do/projects/projectId/types.ts +1 -0
  58. package/src/components/ui/tu-do/projects/task-projects-client.tsx +45 -1
  59. package/src/components/ui/tu-do/projects/types.ts +4 -1
  60. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +10 -0
  61. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +7 -1
  62. package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +87 -2
  63. package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +27 -3
  64. package/src/components/ui/tu-do/shared/__tests__/task-dialog-manager.test.tsx +41 -3
  65. package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +54 -0
  66. package/src/components/ui/tu-do/shared/board-header.tsx +20 -0
  67. package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +4 -4
  68. package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +2 -0
  69. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +7 -0
  70. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/__tests__/use-task-mutations.test.tsx +231 -0
  71. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +139 -68
  72. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.test.tsx +68 -0
  73. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +17 -0
  74. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +45 -23
  75. package/src/components/ui/tu-do/shared/task-row-actions-menu.test.tsx +138 -0
  76. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +15 -9
  77. package/src/components/ui/tu-do/templates/client.tsx +97 -78
  78. package/src/components/ui/tu-do/templates/marketplace/client.tsx +171 -135
  79. package/src/components/ui/tu-do/templates/task-templates-hub.tsx +3 -0
  80. package/src/components/ui/tu-do/templates/templateId/client.tsx +24 -9
  81. package/src/components/ui/tu-do/templates/templateId/task-template-detail-page-client.tsx +8 -2
  82. package/src/hooks/__tests__/use-notifications-subscription.test.tsx +34 -0
  83. package/src/hooks/__tests__/use-task-actions.test.tsx +14 -39
  84. package/src/hooks/task-actions-personal-external.ts +12 -6
  85. package/src/hooks/use-notifications.ts +14 -2
  86. package/vitest.config.ts +4 -0
@@ -152,16 +152,21 @@ export async function moveExternalTaskToPersonalList({
152
152
  const now = new Date().toISOString();
153
153
  let sourceTargetList: TaskList | null = null;
154
154
  const desiredSourceStatus = sourceStatus ?? targetList.status;
155
+ const terminalStatus =
156
+ targetList.status === 'done' || targetList.status === 'closed'
157
+ ? targetList.status
158
+ : undefined;
155
159
  const hasKnownSourceStatusChange = Boolean(
156
160
  task.source_list_status && task.source_list_status !== desiredSourceStatus
157
161
  );
158
162
  const shouldInspectSourceList = Boolean(
159
- sourceStatus ||
160
- hasKnownSourceStatusChange ||
161
- (!task.source_list_status &&
162
- task.source_list_id &&
163
- sourceWorkspaceId &&
164
- sourceBoardId)
163
+ !terminalStatus &&
164
+ (sourceStatus ||
165
+ hasKnownSourceStatusChange ||
166
+ (!task.source_list_status &&
167
+ task.source_list_id &&
168
+ sourceWorkspaceId &&
169
+ sourceBoardId))
165
170
  );
166
171
 
167
172
  try {
@@ -235,6 +240,7 @@ export async function moveExternalTaskToPersonalList({
235
240
  personal_list_id: targetList.id,
236
241
  previous_task_id: order.previous_task_id,
237
242
  next_task_id: order.next_task_id,
243
+ terminal_status: terminalStatus,
238
244
  }
239
245
  );
240
246
 
@@ -90,6 +90,8 @@ interface NotificationSubscriptionEntry {
90
90
  supabase: SupabaseClient;
91
91
  }
92
92
 
93
+ export const UNREAD_COUNT_FALLBACK_INTERVAL_MS = 5 * 60 * 1000;
94
+
93
95
  const notificationSubscriptionRegistry = new Map<
94
96
  string,
95
97
  NotificationSubscriptionEntry
@@ -265,11 +267,13 @@ export function useInfiniteNotifications({
265
267
  unreadOnly = false,
266
268
  readOnly = false,
267
269
  pageSize = 20,
270
+ enabled = true,
268
271
  }: {
269
272
  wsId?: string;
270
273
  unreadOnly?: boolean;
271
274
  readOnly?: boolean;
272
275
  pageSize?: number;
276
+ enabled?: boolean;
273
277
  }) {
274
278
  return useInfiniteQuery({
275
279
  queryKey: [
@@ -299,6 +303,7 @@ export function useInfiniteNotifications({
299
303
  } satisfies NotificationsPage;
300
304
  },
301
305
  initialPageParam: 0,
306
+ enabled,
302
307
  getNextPageParam: (lastPage) => {
303
308
  const nextOffset = lastPage.offset + lastPage.limit;
304
309
  return nextOffset < lastPage.count ? nextOffset : undefined;
@@ -312,7 +317,7 @@ export function useInfiniteNotifications({
312
317
  * Hook to get unread notification count.
313
318
  * If wsId is provided, scopes to that workspace. Otherwise returns total unread count.
314
319
  */
315
- export function useUnreadCount(wsId?: string) {
320
+ export function useUnreadCount(wsId?: string, options?: { enabled?: boolean }) {
316
321
  return useQuery({
317
322
  queryKey: ['notifications', 'unread-count', wsId || 'all'],
318
323
  queryFn: async () => {
@@ -328,7 +333,14 @@ export function useUnreadCount(wsId?: string) {
328
333
  const data = await response.json();
329
334
  return data.count as number;
330
335
  },
331
- refetchInterval: 30000,
336
+ enabled: options?.enabled ?? true,
337
+ staleTime: 60_000,
338
+ // Realtime invalidation is the primary update path. Keep a low-frequency
339
+ // refresh as a safety net for disconnected or suspended browser sessions.
340
+ refetchInterval: UNREAD_COUNT_FALLBACK_INTERVAL_MS,
341
+ refetchIntervalInBackground: false,
342
+ refetchOnReconnect: true,
343
+ refetchOnWindowFocus: true,
332
344
  });
333
345
  }
334
346
 
package/vitest.config.ts CHANGED
@@ -29,6 +29,10 @@ export default defineConfig({
29
29
  find: '@tuturuuu/internal-api',
30
30
  replacement: resolve(__dirname, '../internal-api/src/index.ts'),
31
31
  },
32
+ {
33
+ find: /^@tuturuuu\/types\/primitives\/(.+)$/,
34
+ replacement: `${resolve(__dirname, '../types/src/primitives')}/$1.ts`,
35
+ },
32
36
  {
33
37
  find: '@tuturuuu/supabase/next/client',
34
38
  replacement: resolve(__dirname, '../supabase/src/next/client.ts'),