@crmy/web 0.5.1 → 0.5.6

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 (121) hide show
  1. package/dist/assets/index-CskfWp8E.js +560 -0
  2. package/dist/assets/index-D763l57m.css +1 -0
  3. package/{index.html → dist/index.html} +2 -1
  4. package/package.json +4 -1
  5. package/postcss.config.js +0 -6
  6. package/src/App.tsx +0 -158
  7. package/src/api/client.ts +0 -82
  8. package/src/api/hooks.ts +0 -689
  9. package/src/components/CustomFields.tsx +0 -240
  10. package/src/components/NavLink.tsx +0 -28
  11. package/src/components/crm/AIFab.tsx +0 -37
  12. package/src/components/crm/AccountDrawer.tsx +0 -372
  13. package/src/components/crm/ActivityTimeline.tsx +0 -115
  14. package/src/components/crm/AssignmentDrawer.tsx +0 -396
  15. package/src/components/crm/BriefingPanel.tsx +0 -217
  16. package/src/components/crm/CommandPalette.tsx +0 -254
  17. package/src/components/crm/ContactAvatar.tsx +0 -49
  18. package/src/components/crm/ContactDrawer.tsx +0 -438
  19. package/src/components/crm/ContextPanel.tsx +0 -200
  20. package/src/components/crm/CrmWidgets.tsx +0 -417
  21. package/src/components/crm/DrawerShell.tsx +0 -77
  22. package/src/components/crm/ListToolbar.tsx +0 -252
  23. package/src/components/crm/OpportunityDrawer.tsx +0 -372
  24. package/src/components/crm/PaginationBar.tsx +0 -111
  25. package/src/components/crm/QuickAddDrawer.tsx +0 -652
  26. package/src/components/crm/ShortcutsOverlay.tsx +0 -65
  27. package/src/components/crm/UseCaseDrawer.tsx +0 -454
  28. package/src/components/layout/MobileNav.tsx +0 -49
  29. package/src/components/layout/Sidebar.tsx +0 -157
  30. package/src/components/layout/TopBar.tsx +0 -54
  31. package/src/components/settings/ActorsSettings.tsx +0 -1190
  32. package/src/components/ui/accordion.tsx +0 -52
  33. package/src/components/ui/alert-dialog.tsx +0 -104
  34. package/src/components/ui/alert.tsx +0 -43
  35. package/src/components/ui/aspect-ratio.tsx +0 -5
  36. package/src/components/ui/avatar.tsx +0 -38
  37. package/src/components/ui/badge.tsx +0 -29
  38. package/src/components/ui/breadcrumb.tsx +0 -90
  39. package/src/components/ui/button.tsx +0 -47
  40. package/src/components/ui/calendar.tsx +0 -54
  41. package/src/components/ui/card.tsx +0 -43
  42. package/src/components/ui/carousel.tsx +0 -224
  43. package/src/components/ui/chart.tsx +0 -303
  44. package/src/components/ui/checkbox.tsx +0 -26
  45. package/src/components/ui/collapsible.tsx +0 -9
  46. package/src/components/ui/command.tsx +0 -132
  47. package/src/components/ui/context-menu.tsx +0 -178
  48. package/src/components/ui/date-picker.tsx +0 -313
  49. package/src/components/ui/dialog.tsx +0 -95
  50. package/src/components/ui/drawer.tsx +0 -87
  51. package/src/components/ui/dropdown-menu.tsx +0 -179
  52. package/src/components/ui/form.tsx +0 -129
  53. package/src/components/ui/hover-card.tsx +0 -27
  54. package/src/components/ui/input-otp.tsx +0 -61
  55. package/src/components/ui/input.tsx +0 -22
  56. package/src/components/ui/label.tsx +0 -17
  57. package/src/components/ui/menubar.tsx +0 -207
  58. package/src/components/ui/navigation-menu.tsx +0 -120
  59. package/src/components/ui/pagination.tsx +0 -81
  60. package/src/components/ui/popover.tsx +0 -29
  61. package/src/components/ui/progress.tsx +0 -23
  62. package/src/components/ui/radio-group.tsx +0 -36
  63. package/src/components/ui/resizable.tsx +0 -37
  64. package/src/components/ui/scroll-area.tsx +0 -38
  65. package/src/components/ui/select.tsx +0 -143
  66. package/src/components/ui/separator.tsx +0 -20
  67. package/src/components/ui/sheet.tsx +0 -107
  68. package/src/components/ui/sidebar.tsx +0 -637
  69. package/src/components/ui/skeleton.tsx +0 -7
  70. package/src/components/ui/slider.tsx +0 -23
  71. package/src/components/ui/sonner.tsx +0 -24
  72. package/src/components/ui/switch.tsx +0 -27
  73. package/src/components/ui/table.tsx +0 -72
  74. package/src/components/ui/tabs.tsx +0 -53
  75. package/src/components/ui/textarea.tsx +0 -21
  76. package/src/components/ui/toast.tsx +0 -111
  77. package/src/components/ui/toaster.tsx +0 -24
  78. package/src/components/ui/toggle-group.tsx +0 -49
  79. package/src/components/ui/toggle.tsx +0 -37
  80. package/src/components/ui/tooltip.tsx +0 -28
  81. package/src/components/ui/use-toast.ts +0 -1
  82. package/src/components/ui/utils.ts +0 -9
  83. package/src/contexts/AgentSettingsContext.tsx +0 -24
  84. package/src/hooks/use-mobile.tsx +0 -19
  85. package/src/hooks/use-toast.ts +0 -186
  86. package/src/hooks/useKeyboardShortcuts.ts +0 -95
  87. package/src/hooks/useTheme.ts +0 -24
  88. package/src/index.css +0 -245
  89. package/src/lib/entityColors.ts +0 -18
  90. package/src/lib/stageConfig.ts +0 -32
  91. package/src/lib/utils.ts +0 -6
  92. package/src/main.tsx +0 -25
  93. package/src/pages/Accounts.tsx +0 -205
  94. package/src/pages/Activities.tsx +0 -251
  95. package/src/pages/Agent.tsx +0 -237
  96. package/src/pages/AgentSettings.tsx +0 -544
  97. package/src/pages/Assignments.tsx +0 -750
  98. package/src/pages/Contacts.tsx +0 -200
  99. package/src/pages/Dashboard.tsx +0 -143
  100. package/src/pages/Inbox.tsx +0 -615
  101. package/src/pages/NotFound.tsx +0 -24
  102. package/src/pages/Opportunities.tsx +0 -386
  103. package/src/pages/SearchResults.tsx +0 -49
  104. package/src/pages/Settings.tsx +0 -1884
  105. package/src/pages/UseCases.tsx +0 -396
  106. package/src/pages/auth/Login.tsx +0 -261
  107. package/src/pages/hitl/HITL.tsx +0 -101
  108. package/src/store/appStore.ts +0 -103
  109. package/src/vite-env.d.ts +0 -14
  110. package/tailwind.config.js +0 -121
  111. package/tsconfig.json +0 -24
  112. package/vite.config.ts +0 -27
  113. /package/{public → dist}/android-chrome-192x192.png +0 -0
  114. /package/{public → dist}/android-chrome-512x512.png +0 -0
  115. /package/{public → dist}/apple-touch-icon.png +0 -0
  116. /package/{src/assets/crmy-logo.png → dist/assets/crmy-logo-DWN0xBPW.png} +0 -0
  117. /package/{public → dist}/favicon-16x16.png +0 -0
  118. /package/{public → dist}/favicon-32x32.png +0 -0
  119. /package/{public → dist}/favicon.ico +0 -0
  120. /package/{public → dist}/favicon.svg +0 -0
  121. /package/{public → dist}/site.webmanifest +0 -0
package/src/api/hooks.ts DELETED
@@ -1,689 +0,0 @@
1
- // Copyright 2026 CRMy Contributors
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
5
- import { api } from './client';
6
-
7
- // Generic list hook with pagination
8
- function useList<T>(key: string, path: string, params?: Record<string, string | number | boolean | undefined>) {
9
- const query = new URLSearchParams();
10
- if (params) {
11
- Object.entries(params).forEach(([k, v]) => {
12
- if (v !== undefined && v !== '') query.set(k, String(v));
13
- });
14
- }
15
- const url = query.toString() ? `${path}?${query}` : path;
16
- return useQuery<{ data: T[]; next_cursor?: string; total: number }>({
17
- queryKey: [key, params],
18
- queryFn: () => api.get(url),
19
- });
20
- }
21
-
22
- // Contacts
23
- export function useContacts(params?: { q?: string; limit?: number; cursor?: string }) {
24
- return useList('contacts', 'contacts', params);
25
- }
26
- export function useContact(id: string) {
27
- return useQuery({ queryKey: ['contact', id], queryFn: () => api.get(`contacts/${id}`), enabled: !!id });
28
- }
29
- export function useCreateContact() {
30
- const qc = useQueryClient();
31
- return useMutation({
32
- mutationFn: (data: Record<string, unknown>) => api.post('contacts', data),
33
- onSuccess: () => qc.invalidateQueries({ queryKey: ['contacts'] }),
34
- });
35
- }
36
- export function useUpdateContact(id: string) {
37
- const qc = useQueryClient();
38
- return useMutation({
39
- mutationFn: (data: Record<string, unknown>) => api.patch(`contacts/${id}`, data),
40
- onSuccess: () => {
41
- qc.invalidateQueries({ queryKey: ['contact', id] });
42
- qc.invalidateQueries({ queryKey: ['contacts'] });
43
- },
44
- });
45
- }
46
- export function useDeleteContact(id: string) {
47
- const qc = useQueryClient();
48
- return useMutation({
49
- mutationFn: () => api.delete(`contacts/${id}`),
50
- onSuccess: () => qc.invalidateQueries({ queryKey: ['contacts'] }),
51
- });
52
- }
53
-
54
- // Accounts
55
- export function useAccounts(params?: { q?: string; limit?: number; cursor?: string }) {
56
- return useList('accounts', 'accounts', params);
57
- }
58
- export function useAccount(id: string) {
59
- return useQuery({ queryKey: ['account', id], queryFn: () => api.get(`accounts/${id}`), enabled: !!id });
60
- }
61
- export function useCreateAccount() {
62
- const qc = useQueryClient();
63
- return useMutation({
64
- mutationFn: (data: Record<string, unknown>) => api.post('accounts', data),
65
- onSuccess: () => qc.invalidateQueries({ queryKey: ['accounts'] }),
66
- });
67
- }
68
- export function useUpdateAccount(id: string) {
69
- const qc = useQueryClient();
70
- return useMutation({
71
- mutationFn: (data: Record<string, unknown>) => api.patch(`accounts/${id}`, data),
72
- onSuccess: () => {
73
- qc.invalidateQueries({ queryKey: ['account', id] });
74
- qc.invalidateQueries({ queryKey: ['accounts'] });
75
- },
76
- });
77
- }
78
- export function useDeleteAccount(id: string) {
79
- const qc = useQueryClient();
80
- return useMutation({
81
- mutationFn: () => api.delete(`accounts/${id}`),
82
- onSuccess: () => qc.invalidateQueries({ queryKey: ['accounts'] }),
83
- });
84
- }
85
-
86
- // Opportunities
87
- export function useOpportunities(params?: { q?: string; stage?: string; limit?: number; cursor?: string }) {
88
- return useList('opportunities', 'opportunities', params);
89
- }
90
- export function useOpportunity(id: string) {
91
- return useQuery({ queryKey: ['opportunity', id], queryFn: () => api.get(`opportunities/${id}`), enabled: !!id });
92
- }
93
- export function useCreateOpportunity() {
94
- const qc = useQueryClient();
95
- return useMutation({
96
- mutationFn: (data: Record<string, unknown>) => api.post('opportunities', data),
97
- onSuccess: () => qc.invalidateQueries({ queryKey: ['opportunities'] }),
98
- });
99
- }
100
- export function useUpdateOpportunity(id: string) {
101
- const qc = useQueryClient();
102
- return useMutation({
103
- mutationFn: (data: Record<string, unknown>) => api.patch(`opportunities/${id}`, data),
104
- onSuccess: () => {
105
- qc.invalidateQueries({ queryKey: ['opportunity', id] });
106
- qc.invalidateQueries({ queryKey: ['opportunities'] });
107
- },
108
- });
109
- }
110
- export function useDeleteOpportunity(id: string) {
111
- const qc = useQueryClient();
112
- return useMutation({
113
- mutationFn: () => api.delete(`opportunities/${id}`),
114
- onSuccess: () => qc.invalidateQueries({ queryKey: ['opportunities'] }),
115
- });
116
- }
117
-
118
- // Use Cases
119
- export function useUseCases(params?: { account_id?: string; stage?: string; q?: string; limit?: number; cursor?: string }) {
120
- return useList('use-cases', 'use-cases', params);
121
- }
122
- export function useUseCase(id: string) {
123
- return useQuery({ queryKey: ['use-case', id], queryFn: () => api.get(`use-cases/${id}`), enabled: !!id });
124
- }
125
- export function useCreateUseCase() {
126
- const qc = useQueryClient();
127
- return useMutation({
128
- mutationFn: (data: Record<string, unknown>) => api.post('use-cases', data),
129
- onSuccess: () => qc.invalidateQueries({ queryKey: ['use-cases'] }),
130
- });
131
- }
132
- export function useUpdateUseCase(id: string) {
133
- const qc = useQueryClient();
134
- return useMutation({
135
- mutationFn: (data: Record<string, unknown>) => api.patch(`use-cases/${id}`, data),
136
- onSuccess: () => {
137
- qc.invalidateQueries({ queryKey: ['use-case', id] });
138
- qc.invalidateQueries({ queryKey: ['use-cases'] });
139
- },
140
- });
141
- }
142
- export function useDeleteUseCase(id: string) {
143
- const qc = useQueryClient();
144
- return useMutation({
145
- mutationFn: () => api.delete(`use-cases/${id}`),
146
- onSuccess: () => qc.invalidateQueries({ queryKey: ['use-cases'] }),
147
- });
148
- }
149
- export function useAdvanceUseCaseStage(id: string) {
150
- const qc = useQueryClient();
151
- return useMutation({
152
- mutationFn: (data: { stage: string; note?: string; attributed_arr?: number }) =>
153
- api.post(`use-cases/${id}/stage`, data),
154
- onSuccess: () => {
155
- qc.invalidateQueries({ queryKey: ['use-case', id] });
156
- qc.invalidateQueries({ queryKey: ['use-cases'] });
157
- },
158
- });
159
- }
160
- export function useSetConsumption(id: string) {
161
- const qc = useQueryClient();
162
- return useMutation({
163
- mutationFn: (data: Record<string, unknown>) => api.post(`use-cases/${id}/consumption`, data),
164
- onSuccess: () => qc.invalidateQueries({ queryKey: ['use-case', id] }),
165
- });
166
- }
167
- export function useSetHealth(id: string) {
168
- const qc = useQueryClient();
169
- return useMutation({
170
- mutationFn: (data: { health_score: number; health_note: string }) => api.post(`use-cases/${id}/health`, data),
171
- onSuccess: () => qc.invalidateQueries({ queryKey: ['use-case', id] }),
172
- });
173
- }
174
- export function useUseCaseContacts(id: string) {
175
- return useQuery({
176
- queryKey: ['use-case-contacts', id],
177
- queryFn: () => api.get<{ data: Array<{ contact_id: string; role?: string; contact?: Record<string, unknown> }> }>(`use-cases/${id}/contacts`),
178
- enabled: !!id,
179
- });
180
- }
181
- export function useAddUseCaseContact(id: string) {
182
- const qc = useQueryClient();
183
- return useMutation({
184
- mutationFn: (data: { contact_id: string; role?: string }) => api.post(`use-cases/${id}/contacts`, data),
185
- onSuccess: () => qc.invalidateQueries({ queryKey: ['use-case-contacts', id] }),
186
- });
187
- }
188
- export function useRemoveUseCaseContact(useCaseId: string) {
189
- const qc = useQueryClient();
190
- return useMutation({
191
- mutationFn: (contactId: string) => api.delete(`use-cases/${useCaseId}/contacts/${contactId}`),
192
- onSuccess: () => qc.invalidateQueries({ queryKey: ['use-case-contacts', useCaseId] }),
193
- });
194
- }
195
- export function useUseCaseTimeline(id: string) {
196
- return useQuery({
197
- queryKey: ['use-case-timeline', id],
198
- queryFn: () => api.get(`use-cases/${id}/timeline`),
199
- enabled: !!id,
200
- });
201
- }
202
-
203
- // Activities
204
- export function useActivities(params?: {
205
- contact_id?: string;
206
- account_id?: string;
207
- type?: string;
208
- subject_type?: string;
209
- subject_id?: string;
210
- performed_by?: string;
211
- outcome?: string;
212
- limit?: number;
213
- }) {
214
- return useList('activities', 'activities', params);
215
- }
216
- export function useCreateActivity() {
217
- const qc = useQueryClient();
218
- return useMutation({
219
- mutationFn: (data: Record<string, unknown>) => api.post('activities', data),
220
- onSuccess: () => qc.invalidateQueries({ queryKey: ['activities'] }),
221
- });
222
- }
223
-
224
- // Analytics
225
- export function usePipelineSummary(params?: { owner_id?: string }) {
226
- return useQuery({
227
- queryKey: ['analytics-pipeline', params],
228
- queryFn: () => api.get(`analytics/pipeline${params?.owner_id ? `?owner_id=${params.owner_id}` : ''}`),
229
- });
230
- }
231
- export function usePipelineForecast() {
232
- return useQuery({
233
- queryKey: ['analytics-forecast'],
234
- queryFn: () => api.get('analytics/forecast'),
235
- });
236
- }
237
- export function useUseCaseAnalytics(params?: { account_id?: string; group_by?: string }) {
238
- const query = new URLSearchParams();
239
- if (params?.account_id) query.set('account_id', params.account_id);
240
- if (params?.group_by) query.set('group_by', params.group_by);
241
- const url = query.toString() ? `analytics/use-cases?${query}` : 'analytics/use-cases';
242
- return useQuery({ queryKey: ['analytics-use-cases', params], queryFn: () => api.get(url) });
243
- }
244
-
245
- // HITL
246
- export function useHITLRequests() {
247
- return useQuery({
248
- queryKey: ['hitl'],
249
- queryFn: () => api.get('hitl'),
250
- refetchInterval: 10_000,
251
- });
252
- }
253
- export function useResolveHITL() {
254
- const qc = useQueryClient();
255
- return useMutation({
256
- mutationFn: ({ id, ...data }: { id: string; status: string; note?: string }) =>
257
- api.post(`hitl/${id}/resolve`, data),
258
- onSuccess: () => qc.invalidateQueries({ queryKey: ['hitl'] }),
259
- });
260
- }
261
-
262
- // Webhooks
263
- export function useWebhooks() {
264
- return useList('webhooks', 'webhooks');
265
- }
266
- export function useCreateWebhook() {
267
- const qc = useQueryClient();
268
- return useMutation({
269
- mutationFn: (data: Record<string, unknown>) => api.post('webhooks', data),
270
- onSuccess: () => qc.invalidateQueries({ queryKey: ['webhooks'] }),
271
- });
272
- }
273
- export function useDeleteWebhook() {
274
- const qc = useQueryClient();
275
- return useMutation({
276
- mutationFn: (id: string) => api.delete(`webhooks/${id}`),
277
- onSuccess: () => qc.invalidateQueries({ queryKey: ['webhooks'] }),
278
- });
279
- }
280
-
281
- // Custom Fields
282
- export function useCustomFields(objectType: string) {
283
- return useQuery({
284
- queryKey: ['custom-fields', objectType],
285
- queryFn: () => api.get(`custom-fields?object_type=${objectType}`),
286
- enabled: !!objectType,
287
- });
288
- }
289
- export function useCreateCustomField() {
290
- const qc = useQueryClient();
291
- return useMutation({
292
- mutationFn: (data: Record<string, unknown>) => api.post('custom-fields', data),
293
- onSuccess: () => qc.invalidateQueries({ queryKey: ['custom-fields'] }),
294
- });
295
- }
296
- export function useUpdateCustomField() {
297
- const qc = useQueryClient();
298
- return useMutation({
299
- mutationFn: ({ id, ...data }: { id: string } & Record<string, unknown>) =>
300
- api.patch(`custom-fields/${id}`, data),
301
- onSuccess: () => qc.invalidateQueries({ queryKey: ['custom-fields'] }),
302
- });
303
- }
304
- export function useDeleteCustomField() {
305
- const qc = useQueryClient();
306
- return useMutation({
307
- mutationFn: (id: string) => api.delete(`custom-fields/${id}`),
308
- onSuccess: () => qc.invalidateQueries({ queryKey: ['custom-fields'] }),
309
- });
310
- }
311
-
312
- // Events
313
- export function useEvents(params?: { object_id?: string; limit?: number }) {
314
- return useList('events', 'events', params);
315
- }
316
-
317
- // Search
318
- export function useSearch(q: string) {
319
- return useQuery({
320
- queryKey: ['search', q],
321
- queryFn: () => api.get(`search?q=${encodeURIComponent(q)}`),
322
- enabled: q.length >= 2,
323
- });
324
- }
325
-
326
- // Emails
327
- export function useEmails(params?: { contact_id?: string; status?: string; limit?: number }) {
328
- return useList('emails', 'emails', params);
329
- }
330
- export function useCreateEmail() {
331
- const qc = useQueryClient();
332
- return useMutation({
333
- mutationFn: (data: Record<string, unknown>) => api.post('emails', data),
334
- onSuccess: () => qc.invalidateQueries({ queryKey: ['emails'] }),
335
- });
336
- }
337
-
338
- // Admin: User Management
339
- type AdminUser = { id: string; email: string; name: string; role: string; created_at: string; updated_at?: string };
340
-
341
- export function useUsers() {
342
- return useQuery({
343
- queryKey: ['admin-users'],
344
- queryFn: () => api.get<{ data: AdminUser[] }>('admin/users'),
345
- });
346
- }
347
- export function useCreateUser() {
348
- const qc = useQueryClient();
349
- return useMutation({
350
- mutationFn: (data: { name: string; email: string; password: string; role: string }) =>
351
- api.post<AdminUser>('admin/users', data),
352
- onSuccess: () => qc.invalidateQueries({ queryKey: ['admin-users'] }),
353
- });
354
- }
355
- export function useUpdateUser() {
356
- const qc = useQueryClient();
357
- return useMutation({
358
- mutationFn: ({ id, ...data }: { id: string; name?: string; email?: string; role?: string; password?: string }) =>
359
- api.patch<AdminUser>(`admin/users/${id}`, data),
360
- onSuccess: () => qc.invalidateQueries({ queryKey: ['admin-users'] }),
361
- });
362
- }
363
- export function useDeleteUser() {
364
- const qc = useQueryClient();
365
- return useMutation({
366
- mutationFn: (id: string) => api.delete(`admin/users/${id}`),
367
- onSuccess: () => qc.invalidateQueries({ queryKey: ['admin-users'] }),
368
- });
369
- }
370
-
371
- // Admin: Database Config
372
- export function useDbConfig() {
373
- return useQuery({
374
- queryKey: ['admin-db-config'],
375
- queryFn: () => api.get<{ host: string; port: string; database: string; user: string; ssl: string | null }>('admin/db-config'),
376
- });
377
- }
378
- export function useTestDbConfig() {
379
- return useMutation({
380
- mutationFn: (connection_string: string) => api.post<{ success: boolean }>('admin/db-config/test', { connection_string }),
381
- });
382
- }
383
- export function useSaveDbConfig() {
384
- const qc = useQueryClient();
385
- return useMutation({
386
- mutationFn: (connection_string: string) =>
387
- api.patch<{ success: boolean; message: string }>('admin/db-config', { connection_string }),
388
- onSuccess: () => qc.invalidateQueries({ queryKey: ['admin-db-config'] }),
389
- });
390
- }
391
-
392
- // Notes
393
- export function useNotes(params: { object_type: string; object_id: string }) {
394
- return useList('notes', 'notes', params);
395
- }
396
- export function useCreateNote() {
397
- const qc = useQueryClient();
398
- return useMutation({
399
- mutationFn: (data: Record<string, unknown>) => api.post('notes', data),
400
- onSuccess: () => qc.invalidateQueries({ queryKey: ['notes'] }),
401
- });
402
- }
403
-
404
- // API Keys
405
- export function useApiKeys(actorId?: string) {
406
- const params = actorId ? `?actor_id=${actorId}` : '';
407
- return useQuery({
408
- queryKey: ['api-keys', actorId],
409
- queryFn: () => api.get<{ data: Array<{ id: string; label: string; scopes: string[]; actor_id?: string; actor_name?: string; actor_type?: string; created_at: string; last_used_at?: string }> }>(`/auth/api-keys${params}`),
410
- });
411
- }
412
- export function useCreateApiKey() {
413
- const qc = useQueryClient();
414
- return useMutation({
415
- mutationFn: (data: { label: string; scopes: string[]; actor_id?: string }) =>
416
- api.post<{ id: string; key: string; label: string }>('/auth/api-keys', data),
417
- onSuccess: () => qc.invalidateQueries({ queryKey: ['api-keys'] }),
418
- });
419
- }
420
- export function useUpdateApiKey() {
421
- const qc = useQueryClient();
422
- return useMutation({
423
- mutationFn: ({ id, ...data }: { id: string; label?: string; scopes?: string[]; actor_id?: string | null; expires_at?: string | null }) =>
424
- api.patch(`/auth/api-keys/${id}`, data),
425
- onSuccess: () => qc.invalidateQueries({ queryKey: ['api-keys'] }),
426
- });
427
- }
428
- export function useRevokeApiKey() {
429
- const qc = useQueryClient();
430
- return useMutation({
431
- mutationFn: (id: string) => api.delete(`/auth/api-keys/${id}`),
432
- onSuccess: () => qc.invalidateQueries({ queryKey: ['api-keys'] }),
433
- });
434
- }
435
-
436
- // Profile (self-service)
437
- export function useUpdateProfile() {
438
- return useMutation({
439
- mutationFn: (data: { name?: string; email?: string; current_password?: string; new_password?: string }) =>
440
- api.patch<{ id: string; email: string; name: string; role: string }>('/auth/profile', data),
441
- });
442
- }
443
-
444
- // -- Context Engine hooks (v0.4) --
445
-
446
- // Actors
447
- export function useActors(params?: { actor_type?: string; q?: string; is_active?: boolean; limit?: number }) {
448
- return useList('actors', 'actors', params);
449
- }
450
- export function useActor(id: string) {
451
- return useQuery({ queryKey: ['actor', id], queryFn: () => api.get(`actors/${id}`), enabled: !!id });
452
- }
453
- export function useCreateActor() {
454
- const qc = useQueryClient();
455
- return useMutation({
456
- mutationFn: (data: Record<string, unknown>) => api.post('actors', data),
457
- onSuccess: () => qc.invalidateQueries({ queryKey: ['actors'] }),
458
- });
459
- }
460
- export function useUpdateActor() {
461
- const qc = useQueryClient();
462
- return useMutation({
463
- mutationFn: ({ id, ...patch }: { id: string; [key: string]: unknown }) =>
464
- api.patch(`actors/${id}`, { patch }),
465
- onSuccess: () => {
466
- qc.invalidateQueries({ queryKey: ['actors'] });
467
- qc.invalidateQueries({ queryKey: ['actor'] });
468
- },
469
- });
470
- }
471
- export function useWhoAmI() {
472
- return useQuery({
473
- queryKey: ['actor-whoami'],
474
- queryFn: () => api.get('actors/whoami'),
475
- });
476
- }
477
-
478
- // Assignments
479
- export function useAssignments(params?: {
480
- assigned_to?: string;
481
- assigned_by?: string;
482
- status?: string;
483
- priority?: string;
484
- subject_type?: string;
485
- subject_id?: string;
486
- limit?: number;
487
- }) {
488
- return useList('assignments', 'assignments', params);
489
- }
490
- export function useAssignment(id: string) {
491
- return useQuery({ queryKey: ['assignment', id], queryFn: () => api.get(`assignments/${id}`), enabled: !!id });
492
- }
493
- export function useCreateAssignment() {
494
- const qc = useQueryClient();
495
- return useMutation({
496
- mutationFn: (data: Record<string, unknown>) => api.post('assignments', data),
497
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
498
- });
499
- }
500
- export function useUpdateAssignment(id: string) {
501
- const qc = useQueryClient();
502
- return useMutation({
503
- mutationFn: (data: Record<string, unknown>) => api.patch(`assignments/${id}`, data),
504
- onSuccess: () => {
505
- qc.invalidateQueries({ queryKey: ['assignment', id] });
506
- qc.invalidateQueries({ queryKey: ['assignments'] });
507
- },
508
- });
509
- }
510
- export function useAcceptAssignment() {
511
- const qc = useQueryClient();
512
- return useMutation({
513
- mutationFn: (id: string) => api.post(`assignments/${id}/accept`, {}),
514
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
515
- });
516
- }
517
- export function useCompleteAssignment() {
518
- const qc = useQueryClient();
519
- return useMutation({
520
- mutationFn: ({ id, ...data }: { id: string; completed_by_activity_id?: string }) =>
521
- api.post(`assignments/${id}/complete`, data),
522
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
523
- });
524
- }
525
- export function useDeclineAssignment() {
526
- const qc = useQueryClient();
527
- return useMutation({
528
- mutationFn: ({ id, ...data }: { id: string; reason?: string }) =>
529
- api.post(`assignments/${id}/decline`, data),
530
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
531
- });
532
- }
533
-
534
- // Context Entries
535
- export function useContextEntries(params?: {
536
- subject_type?: string;
537
- subject_id?: string;
538
- context_type?: string;
539
- is_current?: boolean;
540
- limit?: number;
541
- }) {
542
- return useList('context-entries', 'context', params);
543
- }
544
- export function useContextEntry(id: string) {
545
- return useQuery({ queryKey: ['context-entry', id], queryFn: () => api.get(`context/${id}`), enabled: !!id });
546
- }
547
- export function useCreateContextEntry() {
548
- const qc = useQueryClient();
549
- return useMutation({
550
- mutationFn: (data: Record<string, unknown>) => api.post('context', data),
551
- onSuccess: () => qc.invalidateQueries({ queryKey: ['context-entries'] }),
552
- });
553
- }
554
- export function useSupersedeContextEntry() {
555
- const qc = useQueryClient();
556
- return useMutation({
557
- mutationFn: ({ id, ...data }: { id: string; body: string; title?: string }) =>
558
- api.post(`context/${id}/supersede`, data),
559
- onSuccess: () => qc.invalidateQueries({ queryKey: ['context-entries'] }),
560
- });
561
- }
562
- export function useContextSearch(query: string, params?: { subject_type?: string; subject_id?: string; context_type?: string; tag?: string; current_only?: boolean; limit?: number }) {
563
- const searchParams = new URLSearchParams();
564
- searchParams.set('query', query);
565
- if (params) {
566
- Object.entries(params).forEach(([k, v]) => {
567
- if (v !== undefined && v !== '') searchParams.set(k, String(v));
568
- });
569
- }
570
- return useQuery({
571
- queryKey: ['context-search', query, params],
572
- queryFn: () => api.get(`context/search?${searchParams}`),
573
- enabled: query.length >= 2,
574
- });
575
- }
576
- export function useReviewContextEntry() {
577
- const qc = useQueryClient();
578
- return useMutation({
579
- mutationFn: (id: string) => api.post(`context/${id}/review`, {}),
580
- onSuccess: () => {
581
- qc.invalidateQueries({ queryKey: ['context-entries'] });
582
- qc.invalidateQueries({ queryKey: ['context-stale'] });
583
- },
584
- });
585
- }
586
- export function useStaleContextEntries(params?: { subject_type?: string; subject_id?: string; limit?: number }) {
587
- return useList('context-stale', 'context/stale', params);
588
- }
589
-
590
- // Assignment actions (v0.5)
591
- export function useStartAssignment() {
592
- const qc = useQueryClient();
593
- return useMutation({
594
- mutationFn: (id: string) => api.post(`assignments/${id}/start`, {}),
595
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
596
- });
597
- }
598
- export function useBlockAssignment() {
599
- const qc = useQueryClient();
600
- return useMutation({
601
- mutationFn: ({ id, reason }: { id: string; reason?: string }) =>
602
- api.post(`assignments/${id}/block`, { reason }),
603
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
604
- });
605
- }
606
- export function useCancelAssignment() {
607
- const qc = useQueryClient();
608
- return useMutation({
609
- mutationFn: ({ id, reason }: { id: string; reason?: string }) =>
610
- api.post(`assignments/${id}/cancel`, { reason }),
611
- onSuccess: () => qc.invalidateQueries({ queryKey: ['assignments'] }),
612
- });
613
- }
614
-
615
- // Activity Type Registry
616
- export function useActivityTypes(params?: { category?: string }) {
617
- return useList('activity-types', 'activity-types', params);
618
- }
619
- export function useCreateActivityType() {
620
- const qc = useQueryClient();
621
- return useMutation({
622
- mutationFn: (data: { type_name: string; label: string; category: string; description?: string }) =>
623
- api.post('activity-types', data),
624
- onSuccess: () => qc.invalidateQueries({ queryKey: ['activity-types'] }),
625
- });
626
- }
627
- export function useDeleteActivityType() {
628
- const qc = useQueryClient();
629
- return useMutation({
630
- mutationFn: (typeName: string) => api.delete(`activity-types/${typeName}`),
631
- onSuccess: () => qc.invalidateQueries({ queryKey: ['activity-types'] }),
632
- });
633
- }
634
-
635
- // Context Type Registry
636
- export function useContextTypes() {
637
- return useList('context-types', 'context-types');
638
- }
639
- export function useCreateContextType() {
640
- const qc = useQueryClient();
641
- return useMutation({
642
- mutationFn: (data: { type_name: string; label: string; description?: string }) =>
643
- api.post('context-types', data),
644
- onSuccess: () => qc.invalidateQueries({ queryKey: ['context-types'] }),
645
- });
646
- }
647
- export function useDeleteContextType() {
648
- const qc = useQueryClient();
649
- return useMutation({
650
- mutationFn: (typeName: string) => api.delete(`context-types/${typeName}`),
651
- onSuccess: () => qc.invalidateQueries({ queryKey: ['context-types'] }),
652
- });
653
- }
654
-
655
- // Inbox counts (HITL pending + my active assignments) — used by nav badge
656
- export function useInboxCounts() {
657
- const { data: whoami } = useWhoAmI() as any;
658
- const myActorId: string | undefined = whoami?.actor_id;
659
- const hitlQ = useHITLRequests();
660
- const assignQ = useQuery<{ data: any[]; total: number }>({
661
- queryKey: ['inbox-assignments', myActorId],
662
- queryFn: () => api.get(`assignments?assigned_to=${encodeURIComponent(myActorId!)}&limit=200`),
663
- enabled: !!myActorId,
664
- refetchInterval: 30_000,
665
- });
666
- const hitlCount = ((hitlQ.data as any)?.data ?? []).filter((r: any) => r.status === 'pending').length;
667
- const assignCount = ((assignQ.data as any)?.assignments ?? []).filter((a: any) =>
668
- ['pending', 'accepted', 'in_progress', 'blocked'].includes(a.status)
669
- ).length;
670
- return { total: hitlCount + assignCount, hitlCount, assignCount };
671
- }
672
-
673
- // Briefing
674
- export function useBriefing(subjectType: string, subjectId: string, params?: { format?: string; since?: string; context_types?: string; include_stale?: boolean }) {
675
- const searchParams = new URLSearchParams();
676
- if (params) {
677
- Object.entries(params).forEach(([k, v]) => {
678
- if (v !== undefined && v !== '') searchParams.set(k, String(v));
679
- });
680
- }
681
- const qs = searchParams.toString();
682
- const url = `briefing/${subjectType}/${subjectId}${qs ? `?${qs}` : ''}`;
683
- return useQuery({
684
- queryKey: ['briefing', subjectType, subjectId, params],
685
- queryFn: () => api.get(url),
686
- enabled: !!subjectType && !!subjectId,
687
- });
688
- }
689
-