@elevasis/ui 2.67.0 → 2.69.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 (122) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.js +3 -3
  3. package/dist/app/index.d.ts +575 -370
  4. package/dist/app/index.js +17 -23
  5. package/dist/auth/index.css +149 -149
  6. package/dist/auth/index.d.ts +5 -0
  7. package/dist/auth/index.js +11 -13
  8. package/dist/charts/index.css +208 -208
  9. package/dist/charts/index.js +11 -13
  10. package/dist/{chunk-M535KHLW.js → chunk-26BTE3Z4.js} +1 -1
  11. package/dist/chunk-3KMDHCAR.js +52 -0
  12. package/dist/chunk-3MEXPLWT.js +265 -0
  13. package/dist/chunk-4JHLS234.js +39 -0
  14. package/dist/chunk-6PZFOHJK.js +1764 -0
  15. package/dist/chunk-7WJEPTE7.js +194 -0
  16. package/dist/chunk-AH52XQB7.js +1 -0
  17. package/dist/{chunk-UFTM5SZZ.js → chunk-AKANHRQ5.js} +9 -3
  18. package/dist/chunk-BZZCNLT6.js +12 -0
  19. package/dist/chunk-C75XWBYZ.js +383 -0
  20. package/dist/chunk-DLR4SDZW.js +51 -0
  21. package/dist/{chunk-4OEVLV66.js → chunk-FLECOYUS.js} +113 -148
  22. package/dist/chunk-IRV6KJPV.js +425 -0
  23. package/dist/chunk-IT7GTJCB.js +10 -0
  24. package/dist/chunk-LGKLC5MG.js +44 -0
  25. package/dist/chunk-MFLM7BVC.js +85 -0
  26. package/dist/chunk-MRVGQLWN.js +1595 -0
  27. package/dist/{chunk-4DV4ECMG.js → chunk-N7U24M2J.js} +4 -0
  28. package/dist/{chunk-I7BZVVVU.js → chunk-NM4A63KJ.js} +104 -415
  29. package/dist/chunk-NU3NBXHP.js +1194 -0
  30. package/dist/chunk-PDHTXPSF.js +12 -0
  31. package/dist/chunk-RW64UJWT.js +1934 -0
  32. package/dist/{chunk-JFBZ6XDW.js → chunk-SNZDFCOQ.js} +3 -49
  33. package/dist/chunk-TUMSNGTX.js +35 -0
  34. package/dist/chunk-UD657ICS.js +589 -0
  35. package/dist/{chunk-XNW3O6QW.js → chunk-VDX6DL7Z.js} +1 -1
  36. package/dist/chunk-WXHAHKKI.js +16411 -0
  37. package/dist/chunk-XAZR3T6Y.js +2162 -0
  38. package/dist/chunk-XQ3ILKYN.js +37 -0
  39. package/dist/chunk-YCRINA2D.js +67 -0
  40. package/dist/chunk-YGCMMOY4.js +1484 -0
  41. package/dist/chunk-YNRYIXUT.js +10945 -0
  42. package/dist/chunk-ZD6LM53O.js +4528 -0
  43. package/dist/chunk-ZPTEGGKU.js +631 -0
  44. package/dist/components/chat/index.js +2 -1
  45. package/dist/components/index.css +208 -208
  46. package/dist/components/index.d.ts +1634 -264
  47. package/dist/components/index.js +2774 -14
  48. package/dist/components/navigation/index.css +149 -149
  49. package/dist/components/navigation/index.js +12 -13
  50. package/dist/features/auth/index.css +149 -149
  51. package/dist/features/auth/index.d.ts +457 -167
  52. package/dist/features/auth/index.js +13 -14
  53. package/dist/features/clients/index.css +208 -208
  54. package/dist/features/clients/index.d.ts +39 -1
  55. package/dist/features/clients/index.js +16 -13
  56. package/dist/features/content/index.d.ts +1788 -0
  57. package/dist/features/content/index.js +2180 -0
  58. package/dist/features/crm/index.d.ts +1802 -231
  59. package/dist/features/crm/index.js +16 -13
  60. package/dist/features/dashboard/index.d.ts +1 -8
  61. package/dist/features/dashboard/index.js +17 -13
  62. package/dist/features/delivery/index.d.ts +457 -167
  63. package/dist/features/delivery/index.js +16 -13
  64. package/dist/features/knowledge/index.css +149 -149
  65. package/dist/features/knowledge/index.js +11 -13
  66. package/dist/features/lead-gen/index.d.ts +53 -104
  67. package/dist/features/lead-gen/index.js +17 -13
  68. package/dist/features/monitoring/index.js +16 -13
  69. package/dist/features/monitoring/requests/index.js +15 -20
  70. package/dist/features/operations/index.d.ts +1 -86
  71. package/dist/features/operations/index.js +22 -12
  72. package/dist/features/public-agent-chat/index.js +2 -1
  73. package/dist/features/seo/index.js +2 -1
  74. package/dist/features/settings/index.d.ts +457 -167
  75. package/dist/features/settings/index.js +15 -13
  76. package/dist/hooks/access/index.css +149 -149
  77. package/dist/hooks/access/index.d.ts +5 -0
  78. package/dist/hooks/access/index.js +11 -13
  79. package/dist/hooks/delivery/index.d.ts +457 -167
  80. package/dist/hooks/delivery/index.js +2 -23
  81. package/dist/hooks/index.d.ts +2203 -244
  82. package/dist/hooks/index.js +11 -13
  83. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +1 -8
  84. package/dist/hooks/published.d.ts +2203 -244
  85. package/dist/hooks/published.js +11 -13
  86. package/dist/initialization/index.d.ts +465 -169
  87. package/dist/knowledge/index.css +149 -149
  88. package/dist/knowledge/index.d.ts +5 -90
  89. package/dist/knowledge/index.js +3215 -3203
  90. package/dist/{knowledge-search-index-6EZNBNSR.js → knowledge-search-index-LP2WVSQX.js} +689 -695
  91. package/dist/layout/index.css +149 -149
  92. package/dist/layout/index.js +15 -13
  93. package/dist/organization/index.d.ts +10 -4
  94. package/dist/organization/index.js +1 -21
  95. package/dist/profile/index.d.ts +457 -167
  96. package/dist/provider/index.d.ts +576 -372
  97. package/dist/provider/index.js +11 -13
  98. package/dist/provider/published.css +149 -149
  99. package/dist/provider/published.d.ts +576 -372
  100. package/dist/provider/published.js +11 -13
  101. package/dist/supabase/index.d.ts +906 -347
  102. package/dist/test-utils/index.d.ts +15 -2
  103. package/dist/test-utils/index.js +41 -12
  104. package/dist/test-utils/setup-integration.js +1 -1
  105. package/dist/test-utils/setup.js +1 -1
  106. package/dist/theme/index.js +3 -2
  107. package/dist/theme/presets/index.js +1 -1
  108. package/dist/typeform/index.js +2049 -1
  109. package/dist/types/index.d.ts +477 -177
  110. package/dist/utils/index.d.ts +1 -8
  111. package/dist/utils/index.js +1 -1
  112. package/dist/vite/index.js +2 -2
  113. package/dist/vite-plugin-knowledge/index.js +1 -1
  114. package/package.json +7 -3
  115. package/src/features/README.md +28 -28
  116. package/dist/chunk-5TERYXOO.js +0 -51390
  117. package/dist/chunk-AUDNF2Q7.js +0 -2050
  118. package/dist/index.d.ts +0 -17888
  119. package/dist/index.js +0 -30
  120. package/dist/{chunk-GMXGDO3I.js → chunk-MISHPEJX.js} +1 -1
  121. package/dist/{chunk-RBGVNPA6.js → chunk-XQBURFKM.js} +0 -0
  122. package/dist/{index.css → features/content/index.css} +149 -149
@@ -0,0 +1,194 @@
1
+ import { getLeadGenStageCatalog } from './chunk-WXHAHKKI.js';
2
+ import { SYSTEM_INTERFACE_PROFILES, formatOntologyId, registerBuiltInReadinessProfile, registerReadinessInterfaceMarker, requireContractReadiness, computeInterfaceReadiness, addReadinessIssue, formatInterfaceIdentity, resourceBindingIds, requireCatalogReadiness, requireScopedBinding } from './chunk-NM4A63KJ.js';
3
+
4
+ // ../core/src/business/acquisition/ontology-validation.ts
5
+ var LEAD_GEN_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[0];
6
+ var CRM_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[1];
7
+ var LEAD_GEN_CRM_HANDOFF_INTERFACE = SYSTEM_INTERFACE_PROFILES[2];
8
+ LEAD_GEN_API_INTERFACE.readinessProfile;
9
+ CRM_API_INTERFACE.readinessProfile;
10
+ LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile;
11
+ var LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID = formatOntologyId({
12
+ scope: "sales.lead-gen",
13
+ kind: "object",
14
+ localId: "list"
15
+ });
16
+ var LEAD_GEN_COMPANY_OBJECT_ONTOLOGY_ID = formatOntologyId({
17
+ scope: "sales.lead-gen",
18
+ kind: "object",
19
+ localId: "company"
20
+ });
21
+ var LEAD_GEN_CONTACT_OBJECT_ONTOLOGY_ID = formatOntologyId({
22
+ scope: "sales.lead-gen",
23
+ kind: "object",
24
+ localId: "contact"
25
+ });
26
+ var LEAD_GEN_BUILD_TEMPLATE_CATALOG_ONTOLOGY_ID = formatOntologyId({
27
+ scope: "sales.lead-gen",
28
+ kind: "catalog",
29
+ localId: "build-template"
30
+ });
31
+ var LEAD_GEN_COMPANY_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
32
+ scope: "sales.lead-gen",
33
+ kind: "catalog",
34
+ localId: "company-stage"
35
+ });
36
+ var LEAD_GEN_CONTACT_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
37
+ scope: "sales.lead-gen",
38
+ kind: "catalog",
39
+ localId: "contact-stage"
40
+ });
41
+ var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
42
+ scope: "sales.crm",
43
+ kind: "catalog",
44
+ localId: "crm.pipeline"
45
+ });
46
+ var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
47
+ scope: "sales.lead-gen",
48
+ kind: "catalog",
49
+ localId: "lead-gen.stage-catalog"
50
+ });
51
+ var LEAD_GEN_API_READINESS_CONTRACT = {
52
+ requiredObjects: [
53
+ LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID,
54
+ LEAD_GEN_COMPANY_OBJECT_ONTOLOGY_ID,
55
+ LEAD_GEN_CONTACT_OBJECT_ONTOLOGY_ID
56
+ ],
57
+ requiredCatalogs: [
58
+ LEAD_GEN_BUILD_TEMPLATE_CATALOG_ONTOLOGY_ID,
59
+ LEAD_GEN_COMPANY_STAGE_CATALOG_ONTOLOGY_ID,
60
+ LEAD_GEN_CONTACT_STAGE_CATALOG_ONTOLOGY_ID
61
+ ]
62
+ };
63
+ var CRM_API_READINESS_CONTRACT = {
64
+ requiredObjects: [],
65
+ requiredCatalogs: [CRM_PIPELINE_CATALOG_ONTOLOGY_ID]
66
+ };
67
+ function isPlainRecord(value) {
68
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
69
+ }
70
+ function createLeadGenStageCatalog(model) {
71
+ return {
72
+ id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
73
+ label: "Lead Gen Processing Stages",
74
+ ownerSystemId: "sales.lead-gen",
75
+ kind: "processing-stage-catalog",
76
+ entries: Object.fromEntries(
77
+ Object.entries(getLeadGenStageCatalog(model)).map(([key, entry]) => [
78
+ key,
79
+ {
80
+ ...entry
81
+ }
82
+ ])
83
+ ),
84
+ legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
85
+ };
86
+ }
87
+ function requireLeadGenSupplementalReadiness(issues, index, resources, context) {
88
+ const catalogs = resourceBindingIds(resources, "usesCatalogs");
89
+ const templateStepCatalog = findLeadGenTemplateStepCatalog(index);
90
+ if (templateStepCatalog === void 0) {
91
+ addReadinessIssue(
92
+ issues,
93
+ "SYSTEM_INTERFACE_NOT_READY",
94
+ "missing-template-step-catalog",
95
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing a lead-gen template-step catalog.`
96
+ );
97
+ } else {
98
+ requireCatalogReadiness(issues, index, templateStepCatalog.id, context);
99
+ requireScopedBinding(issues, catalogs, "usesCatalogs", templateStepCatalog.id, context);
100
+ }
101
+ requireCatalogReadiness(issues, index, LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID, context);
102
+ }
103
+ function requireLeadGenInterfaceReadiness(issues, index, resources, context) {
104
+ requireContractReadiness(issues, index, resources, LEAD_GEN_API_READINESS_CONTRACT, context);
105
+ requireLeadGenSupplementalReadiness(issues, index, resources, context);
106
+ }
107
+ function requireCrmInterfaceReadiness(issues, index, resources, context) {
108
+ requireContractReadiness(issues, index, resources, CRM_API_READINESS_CONTRACT, context);
109
+ }
110
+ function findSystemInterfaceGrant(model, consumer, provider) {
111
+ return Object.values(model.topology?.relationships ?? {}).find((relationship) => {
112
+ const grant = relationship.metadata?.["systemInterfaceGrant"];
113
+ if (!isPlainRecord(grant) || !isPlainRecord(grant.consumer) || !isPlainRecord(grant.provider)) return false;
114
+ return grant.consumer.systemPath === consumer.systemPath && grant.consumer.interfaceKey === consumer.interfaceKey && grant.provider.systemPath === provider.systemPath && grant.provider.interfaceKey === provider.interfaceKey;
115
+ });
116
+ }
117
+ function requireHandoffBridgeReadiness(issues, model, context) {
118
+ const crmResult = computeInterfaceReadiness(model, CRM_API_INTERFACE);
119
+ if (!crmResult.ready) {
120
+ for (const issue of crmResult.issues) {
121
+ addReadinessIssue(
122
+ issues,
123
+ "SYSTEM_BRIDGE_NOT_READY",
124
+ issue.code,
125
+ `Provider interface ${formatInterfaceIdentity(CRM_API_INTERFACE.systemPath, CRM_API_INTERFACE.interfaceKey)} is not ready: ${issue.message}`,
126
+ { path: issue.path, ref: issue.ref }
127
+ );
128
+ }
129
+ }
130
+ const bridgeGrant = findSystemInterfaceGrant(model, context, CRM_API_INTERFACE);
131
+ if (bridgeGrant === void 0) {
132
+ addReadinessIssue(
133
+ issues,
134
+ "SYSTEM_BRIDGE_NOT_READY",
135
+ "missing-topology-grant",
136
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires a scoped topology grant to "${formatInterfaceIdentity(CRM_API_INTERFACE.systemPath, CRM_API_INTERFACE.interfaceKey)}".`
137
+ );
138
+ }
139
+ return bridgeGrant;
140
+ }
141
+ function getLeadGenCrmHandoffResourceIds(model) {
142
+ return Object.values(model.resources ?? {}).filter(
143
+ (resource) => resource.systemPath === LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath && resource.ontology?.usesCatalogs?.includes(CRM_PIPELINE_CATALOG_ONTOLOGY_ID) === true
144
+ ).map((resource) => resource.id);
145
+ }
146
+ function mergeLeadGenDerivedCatalogs(model) {
147
+ const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
148
+ const derivedCatalogTypes = {};
149
+ if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
150
+ derivedCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog(model);
151
+ }
152
+ if (Object.keys(derivedCatalogTypes).length === 0) return model;
153
+ return {
154
+ ...model,
155
+ ontology: {
156
+ ...model.ontology ?? {},
157
+ catalogTypes: {
158
+ ...baseCatalogTypes,
159
+ ...derivedCatalogTypes
160
+ }
161
+ }
162
+ };
163
+ }
164
+ registerBuiltInReadinessProfile(LEAD_GEN_API_INTERFACE.readinessProfile, {
165
+ validate: (issues, index, resources, _model, context) => requireLeadGenInterfaceReadiness(issues, index, resources, context),
166
+ prepareModel: mergeLeadGenDerivedCatalogs
167
+ });
168
+ registerBuiltInReadinessProfile(CRM_API_INTERFACE.readinessProfile, {
169
+ validate: (issues, index, resources, _model, context) => requireCrmInterfaceReadiness(issues, index, resources, context)
170
+ });
171
+ registerBuiltInReadinessProfile(LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile, {
172
+ validate: (issues, index, resources, model, context) => {
173
+ requireLeadGenInterfaceReadiness(issues, index, resources, context);
174
+ requireCrmInterfaceReadiness(issues, index, resources, { ...context, allowForeignOwner: true });
175
+ requireHandoffBridgeReadiness(issues, model, context);
176
+ },
177
+ prepareModel: mergeLeadGenDerivedCatalogs
178
+ });
179
+ registerReadinessInterfaceMarker(
180
+ LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath,
181
+ LEAD_GEN_CRM_HANDOFF_INTERFACE.interfaceKey,
182
+ (model) => ({
183
+ lifecycle: "active",
184
+ readinessProfile: LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile,
185
+ resourceIds: getLeadGenCrmHandoffResourceIds(model)
186
+ })
187
+ );
188
+ function findLeadGenTemplateStepCatalog(index) {
189
+ return Object.values(index.ontology.catalogTypes).find(
190
+ (catalog) => catalog.ownerSystemId === "sales.lead-gen" && catalog.kind === "template-step" && catalog.appliesTo === LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID
191
+ );
192
+ }
193
+
194
+ export { CRM_API_INTERFACE, LEAD_GEN_API_INTERFACE };
@@ -0,0 +1 @@
1
+
@@ -25,11 +25,17 @@ function detectLayout(viteRoot) {
25
25
  return {
26
26
  mode: "monorepo",
27
27
  projectRoot,
28
- omSourcePath: resolve(projectRoot, "packages/elevasis-core/src/organization-model/index.ts"),
28
+ omSourcePath: resolve(projectRoot, "packages/elevasis/core/config/organization-model.ts"),
29
29
  // monorepo mode does not consume mdxNodesDir; field kept for type uniformity
30
- mdxNodesDir: resolve(projectRoot, "packages/elevasis-core/knowledge-nodes-unused"),
30
+ mdxNodesDir: resolve(projectRoot, "packages/elevasis/core/knowledge-nodes-unused"),
31
31
  generatedDir: resolve(projectRoot, "packages/ui/src/knowledge/_generated"),
32
- watchPaths: [resolve(projectRoot, "packages/elevasis-core/src/organization-model")]
32
+ // Both, and the knowledge dir is the load-bearing one: monorepo runCodegen
33
+ // regenerates from the MDX bodies, so watching only the OM meant a node edit
34
+ // never hot-regenerated. Pre-dates the move — the paths changed, the gap did not.
35
+ watchPaths: [
36
+ resolve(projectRoot, "packages/elevasis/core/config/organization-model"),
37
+ resolve(projectRoot, "packages/elevasis/core/config/knowledge/nodes")
38
+ ]
33
39
  };
34
40
  }
35
41
  const parent = resolve(dir, "..");
@@ -0,0 +1,12 @@
1
+ import { Container, Stack } from '@mantine/core';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/components/layout/shell/PageContainer.tsx
5
+ var PageContainer = ({ children }) => {
6
+ return (
7
+ // Add padding to the top of the container to adjust for the topbar height
8
+ /* @__PURE__ */ jsx(Container, { size: "xl", p: 0, w: "100%", children: /* @__PURE__ */ jsx(Stack, { gap: "lg", children }) })
9
+ );
10
+ };
11
+
12
+ export { PageContainer };
@@ -0,0 +1,383 @@
1
+ import { getErrorInfo, formatErrorMessage, getErrorTitle } from './chunk-NM4A63KJ.js';
2
+ import { useElevasisServices } from './chunk-BI5VDO2K.js';
3
+ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
4
+ import { notifications } from '@mantine/notifications';
5
+
6
+ var showInfoNotification = (message) => {
7
+ notifications.show({
8
+ title: "Info",
9
+ message,
10
+ autoClose: 5e3,
11
+ color: "blue",
12
+ position: "top-right"
13
+ });
14
+ };
15
+ var showSuccessNotification = (message) => {
16
+ notifications.show({
17
+ title: "Action Successful",
18
+ message,
19
+ autoClose: 5e3,
20
+ color: "green",
21
+ position: "top-right"
22
+ });
23
+ };
24
+ var showErrorNotification = (error) => {
25
+ if (error instanceof Error) {
26
+ error = error.message;
27
+ }
28
+ notifications.show({
29
+ title: "Action Failed",
30
+ message: error,
31
+ autoClose: 5e3,
32
+ color: "red",
33
+ position: "top-right"
34
+ });
35
+ };
36
+ var showWarningNotification = (message) => {
37
+ notifications.show({
38
+ title: "Warning",
39
+ message,
40
+ autoClose: 5e3,
41
+ color: "orange",
42
+ position: "top-right"
43
+ });
44
+ };
45
+ var showApiErrorNotification = (error) => {
46
+ const { message, code, requestId, fields, retryAfter } = getErrorInfo(error);
47
+ notifications.show({
48
+ title: getErrorTitle(code),
49
+ message: formatErrorMessage(message, requestId, fields, retryAfter),
50
+ autoClose: retryAfter ? retryAfter * 1e3 : 5e3,
51
+ color: "red",
52
+ position: "top-right"
53
+ });
54
+ };
55
+ var milestoneKeys = {
56
+ all: ["project-milestones"],
57
+ lists: () => [...milestoneKeys.all, "list"],
58
+ list: (orgId, filters) => [...milestoneKeys.all, "list", orgId, filters],
59
+ details: () => [...milestoneKeys.all, "detail"],
60
+ detail: (id) => [...milestoneKeys.all, "detail", id]
61
+ };
62
+ function useMilestones(filters = {}) {
63
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
64
+ return useQuery({
65
+ queryKey: milestoneKeys.list(workOSOrganizationId, filters),
66
+ queryFn: async () => {
67
+ const res = await apiRequest(`/projects/${filters.projectId}/milestones`);
68
+ return res.milestones;
69
+ },
70
+ enabled: isReady && !!filters.projectId
71
+ });
72
+ }
73
+ function useCreateMilestone() {
74
+ const { apiRequest } = useElevasisServices();
75
+ const queryClient = useQueryClient();
76
+ return useMutation({
77
+ mutationFn: async (params) => {
78
+ const { project_id, ...body } = params;
79
+ if (!project_id) throw new Error("project_id is required to create a milestone");
80
+ const res = await apiRequest(`/projects/${project_id}/milestones`, {
81
+ method: "POST",
82
+ body: JSON.stringify(body)
83
+ });
84
+ return res.milestone;
85
+ },
86
+ onSuccess: (data) => {
87
+ queryClient.invalidateQueries({ queryKey: milestoneKeys.all });
88
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
89
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(data.project_id) });
90
+ },
91
+ onError: (error) => {
92
+ showApiErrorNotification(error);
93
+ }
94
+ });
95
+ }
96
+ function useUpdateMilestone() {
97
+ const { apiRequest } = useElevasisServices();
98
+ const queryClient = useQueryClient();
99
+ return useMutation({
100
+ mutationFn: async (params) => {
101
+ const res = await apiRequest(`/milestones/${params.id}`, {
102
+ method: "PATCH",
103
+ body: JSON.stringify(params.updates)
104
+ });
105
+ return res.milestone;
106
+ },
107
+ onSuccess: (data) => {
108
+ queryClient.invalidateQueries({ queryKey: milestoneKeys.all });
109
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
110
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(data.project_id) });
111
+ },
112
+ onError: (error) => {
113
+ showApiErrorNotification(error);
114
+ }
115
+ });
116
+ }
117
+ function useDeleteMilestone() {
118
+ const { apiRequest } = useElevasisServices();
119
+ const queryClient = useQueryClient();
120
+ return useMutation({
121
+ mutationFn: async (params) => {
122
+ await apiRequest(`/milestones/${params.id}`, {
123
+ method: "DELETE"
124
+ });
125
+ },
126
+ onSuccess: (_, params) => {
127
+ queryClient.invalidateQueries({ queryKey: milestoneKeys.all });
128
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
129
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(params.projectId) });
130
+ },
131
+ onError: (error) => {
132
+ showApiErrorNotification(error);
133
+ }
134
+ });
135
+ }
136
+ var taskKeys = {
137
+ all: ["project-tasks"],
138
+ lists: () => [...taskKeys.all, "list"],
139
+ list: (orgId, filters) => [...taskKeys.all, "list", orgId, filters],
140
+ details: () => [...taskKeys.all, "detail"],
141
+ detail: (id) => [...taskKeys.all, "detail", id]
142
+ };
143
+ function useTasks(filters = {}) {
144
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
145
+ return useQuery({
146
+ queryKey: taskKeys.list(workOSOrganizationId, filters),
147
+ queryFn: async () => {
148
+ const params = new URLSearchParams();
149
+ if (filters.status) params.set("status", filters.status);
150
+ if (filters.milestoneId) params.set("milestone_id", filters.milestoneId);
151
+ const qs = params.toString();
152
+ const base = `/projects/${filters.projectId}/tasks`;
153
+ const path = qs ? `${base}?${qs}` : base;
154
+ const res = await apiRequest(path);
155
+ return res.tasks;
156
+ },
157
+ enabled: isReady && !!filters.projectId
158
+ });
159
+ }
160
+ function useCreateTask() {
161
+ const { apiRequest } = useElevasisServices();
162
+ const queryClient = useQueryClient();
163
+ return useMutation({
164
+ mutationFn: async (params) => {
165
+ const res = await apiRequest("/project-tasks", {
166
+ method: "POST",
167
+ body: JSON.stringify(params)
168
+ });
169
+ return res.task;
170
+ },
171
+ onSuccess: (data) => {
172
+ queryClient.invalidateQueries({ queryKey: taskKeys.all });
173
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
174
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(data.project_id) });
175
+ },
176
+ onError: (error) => {
177
+ showApiErrorNotification(error);
178
+ }
179
+ });
180
+ }
181
+ function useUpdateTask() {
182
+ const { apiRequest } = useElevasisServices();
183
+ const queryClient = useQueryClient();
184
+ return useMutation({
185
+ mutationFn: async (params) => {
186
+ const res = await apiRequest(`/project-tasks/${params.id}`, {
187
+ method: "PATCH",
188
+ body: JSON.stringify(params.updates)
189
+ });
190
+ return res.task;
191
+ },
192
+ onSuccess: (data) => {
193
+ queryClient.invalidateQueries({ queryKey: taskKeys.all });
194
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
195
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(data.project_id) });
196
+ },
197
+ onError: (error) => {
198
+ showApiErrorNotification(error);
199
+ }
200
+ });
201
+ }
202
+ function useDeleteTask() {
203
+ const { apiRequest } = useElevasisServices();
204
+ const queryClient = useQueryClient();
205
+ return useMutation({
206
+ mutationFn: async (params) => {
207
+ await apiRequest(`/project-tasks/${params.id}`, {
208
+ method: "DELETE"
209
+ });
210
+ },
211
+ onSuccess: (_, params) => {
212
+ queryClient.invalidateQueries({ queryKey: taskKeys.all });
213
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
214
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(params.projectId) });
215
+ },
216
+ onError: (error) => {
217
+ showApiErrorNotification(error);
218
+ }
219
+ });
220
+ }
221
+ var noteKeys = {
222
+ all: ["project-notes"],
223
+ lists: () => [...noteKeys.all, "list"],
224
+ list: (orgId, filters) => [...noteKeys.all, "list", orgId, filters],
225
+ details: () => [...noteKeys.all, "detail"],
226
+ detail: (id) => [...noteKeys.all, "detail", id]
227
+ };
228
+ function useProjectNotes(filters = {}) {
229
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
230
+ return useQuery({
231
+ queryKey: noteKeys.list(workOSOrganizationId, filters),
232
+ queryFn: async () => {
233
+ const res = await apiRequest(`/projects/${filters.projectId}/notes`);
234
+ return res.notes;
235
+ },
236
+ enabled: isReady && !!filters.projectId
237
+ });
238
+ }
239
+ function useCreateNote() {
240
+ const { apiRequest } = useElevasisServices();
241
+ const queryClient = useQueryClient();
242
+ return useMutation({
243
+ mutationFn: async (params) => {
244
+ const res = await apiRequest("/project-notes", {
245
+ method: "POST",
246
+ body: JSON.stringify(params)
247
+ });
248
+ return res.note;
249
+ },
250
+ onSuccess: (data) => {
251
+ queryClient.invalidateQueries({ queryKey: noteKeys.all });
252
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
253
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(data.project_id) });
254
+ },
255
+ onError: (error) => {
256
+ showApiErrorNotification(error);
257
+ }
258
+ });
259
+ }
260
+
261
+ // src/hooks/delivery/useProjects.ts
262
+ var projectKeys = {
263
+ all: ["projects"],
264
+ lists: () => [...projectKeys.all, "list"],
265
+ list: (orgId, filters) => [...projectKeys.all, "list", orgId, filters],
266
+ details: () => [...projectKeys.all, "detail"],
267
+ detail: (id) => [...projectKeys.all, "detail", id],
268
+ milestones: (id) => [...projectKeys.all, id, "milestones"],
269
+ tasks: (id) => [...projectKeys.all, id, "tasks"]
270
+ };
271
+ function useProjects(filters = {}) {
272
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
273
+ return useQuery({
274
+ queryKey: projectKeys.list(workOSOrganizationId, filters),
275
+ queryFn: async () => {
276
+ const params = new URLSearchParams();
277
+ if (filters.kind) params.set("kind", filters.kind);
278
+ const qs = params.toString();
279
+ const path = qs ? `/projects?${qs}` : "/projects";
280
+ const res = await apiRequest(path);
281
+ return res.projects;
282
+ },
283
+ enabled: isReady
284
+ });
285
+ }
286
+ function useProject(id) {
287
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
288
+ return useQuery({
289
+ queryKey: [...projectKeys.detail(id), workOSOrganizationId],
290
+ queryFn: async () => {
291
+ try {
292
+ const res = await apiRequest(`/projects/${id}`);
293
+ return res.project;
294
+ } catch (err) {
295
+ if (err && typeof err === "object" && "statusCode" in err && err.statusCode === 404) {
296
+ return null;
297
+ }
298
+ throw err;
299
+ }
300
+ },
301
+ enabled: isReady && !!id
302
+ });
303
+ }
304
+ function useProjectMilestones(projectId) {
305
+ const { apiRequest, isReady } = useElevasisServices();
306
+ return useQuery({
307
+ queryKey: projectKeys.milestones(projectId),
308
+ queryFn: async () => {
309
+ const res = await apiRequest(`/projects/${projectId}/milestones`);
310
+ return res.milestones;
311
+ },
312
+ enabled: isReady && !!projectId
313
+ });
314
+ }
315
+ function useProjectTasks(projectId) {
316
+ const { apiRequest, isReady } = useElevasisServices();
317
+ return useQuery({
318
+ queryKey: projectKeys.tasks(projectId),
319
+ queryFn: async () => {
320
+ const res = await apiRequest(`/projects/${projectId}/tasks`);
321
+ return res.tasks;
322
+ },
323
+ enabled: isReady && !!projectId
324
+ });
325
+ }
326
+ function useCreateProject() {
327
+ const { apiRequest } = useElevasisServices();
328
+ const queryClient = useQueryClient();
329
+ return useMutation({
330
+ mutationFn: async (params) => {
331
+ const res = await apiRequest("/projects", {
332
+ method: "POST",
333
+ body: JSON.stringify(params)
334
+ });
335
+ return res.project;
336
+ },
337
+ onSuccess: () => {
338
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
339
+ },
340
+ onError: (error) => {
341
+ showApiErrorNotification(error);
342
+ }
343
+ });
344
+ }
345
+ function useUpdateProject() {
346
+ const { apiRequest } = useElevasisServices();
347
+ const queryClient = useQueryClient();
348
+ return useMutation({
349
+ mutationFn: async (params) => {
350
+ const res = await apiRequest(`/projects/${params.id}`, {
351
+ method: "PATCH",
352
+ body: JSON.stringify(params.updates)
353
+ });
354
+ return res.project;
355
+ },
356
+ onSuccess: (data) => {
357
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
358
+ queryClient.invalidateQueries({ queryKey: projectKeys.detail(data.id) });
359
+ },
360
+ onError: (error) => {
361
+ showApiErrorNotification(error);
362
+ }
363
+ });
364
+ }
365
+ function useDeleteProject() {
366
+ const { apiRequest } = useElevasisServices();
367
+ const queryClient = useQueryClient();
368
+ return useMutation({
369
+ mutationFn: async (id) => {
370
+ await apiRequest(`/projects/${id}`, {
371
+ method: "DELETE"
372
+ });
373
+ },
374
+ onSuccess: () => {
375
+ queryClient.invalidateQueries({ queryKey: projectKeys.all });
376
+ },
377
+ onError: (error) => {
378
+ showApiErrorNotification(error);
379
+ }
380
+ });
381
+ }
382
+
383
+ export { milestoneKeys, noteKeys, projectKeys, showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, taskKeys, useCreateMilestone, useCreateNote, useCreateProject, useCreateTask, useDeleteMilestone, useDeleteProject, useDeleteTask, useMilestones, useProject, useProjectMilestones, useProjectNotes, useProjectTasks, useProjects, useTasks, useUpdateMilestone, useUpdateProject, useUpdateTask };
@@ -0,0 +1,51 @@
1
+ // src/features/delivery/_shared.ts
2
+ var projectStatusColors = {
3
+ active: "blue",
4
+ on_track: "green",
5
+ at_risk: "yellow",
6
+ blocked: "red",
7
+ completed: "teal",
8
+ paused: "gray"
9
+ };
10
+ var milestoneStatusColors = {
11
+ upcoming: "gray",
12
+ in_progress: "blue",
13
+ completed: "green",
14
+ overdue: "red",
15
+ blocked: "orange"
16
+ };
17
+ var taskStatusColors = {
18
+ pending: "gray",
19
+ planned: "gray",
20
+ in_progress: "blue",
21
+ blocked: "red",
22
+ completed: "green",
23
+ cancelled: "gray",
24
+ submitted: "yellow",
25
+ approved: "green",
26
+ rejected: "red",
27
+ revision_requested: "orange"
28
+ };
29
+ var taskTypeColors = {
30
+ documentation: "blue",
31
+ code: "violet",
32
+ report: "cyan",
33
+ design: "pink",
34
+ other: "gray"
35
+ };
36
+ var noteTypeColors = {
37
+ call_note: "blue",
38
+ status_update: "green",
39
+ issue: "yellow",
40
+ blocker: "red",
41
+ agent_learning: "grape"
42
+ };
43
+ function formatStatusLabel(status) {
44
+ return status.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
45
+ }
46
+ function calculateProgress(completed, total) {
47
+ if (total === 0) return 0;
48
+ return Math.round(completed / total * 100);
49
+ }
50
+
51
+ export { calculateProgress, formatStatusLabel, milestoneStatusColors, noteTypeColors, projectStatusColors, taskStatusColors, taskTypeColors };