@burdenoff/microfe-proserviceworld 2026.703.1 → 2026.706.2
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/dist/index.js +2 -3
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/dist/proserviceworld/ProServiceWorldRoot.js +92 -136
- package/dist/proserviceworld/ProServiceWorldRoot.js.map +1 -1
- package/dist/proserviceworld/ProServiceWorldRoutes.js +18 -26
- package/dist/proserviceworld/ProServiceWorldRoutes.js.map +1 -1
- package/dist/proserviceworld/components/DiscussionThread.js +76 -0
- package/dist/proserviceworld/components/DiscussionThread.js.map +1 -0
- package/dist/proserviceworld/components/ui.js +273 -0
- package/dist/proserviceworld/components/ui.js.map +1 -0
- package/dist/proserviceworld/hooks/useEntityComments.js +56 -0
- package/dist/proserviceworld/hooks/useEntityComments.js.map +1 -0
- package/dist/proserviceworld/hooks/useFiles.js +45 -0
- package/dist/proserviceworld/hooks/useFiles.js.map +1 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js +416 -0
- package/dist/proserviceworld/hooks/useProServiceWorldApi.js.map +1 -0
- package/dist/proserviceworld/index.js +0 -1
- package/dist/proserviceworld/pages/AnalyticsPage.js +163 -475
- package/dist/proserviceworld/pages/AnalyticsPage.js.map +1 -1
- package/dist/proserviceworld/pages/ClientDetailPage.js +243 -0
- package/dist/proserviceworld/pages/ClientDetailPage.js.map +1 -0
- package/dist/proserviceworld/pages/ClientsPage.js +295 -0
- package/dist/proserviceworld/pages/ClientsPage.js.map +1 -0
- package/dist/proserviceworld/pages/CompliancePage.js +307 -0
- package/dist/proserviceworld/pages/CompliancePage.js.map +1 -0
- package/dist/proserviceworld/pages/ConflictsPage.js +234 -0
- package/dist/proserviceworld/pages/ConflictsPage.js.map +1 -0
- package/dist/proserviceworld/pages/DashboardPage.js +179 -632
- package/dist/proserviceworld/pages/DashboardPage.js.map +1 -1
- package/dist/proserviceworld/pages/DocumentsPage.js +235 -539
- package/dist/proserviceworld/pages/DocumentsPage.js.map +1 -1
- package/dist/proserviceworld/pages/EngagementDetailPage.js +449 -0
- package/dist/proserviceworld/pages/EngagementDetailPage.js.map +1 -0
- package/dist/proserviceworld/pages/EngagementsPage.js +256 -0
- package/dist/proserviceworld/pages/EngagementsPage.js.map +1 -0
- package/dist/proserviceworld/pages/InvoicesPage.js +303 -0
- package/dist/proserviceworld/pages/InvoicesPage.js.map +1 -0
- package/dist/proserviceworld/pages/MattersPage.js +275 -0
- package/dist/proserviceworld/pages/MattersPage.js.map +1 -0
- package/dist/proserviceworld/pages/PracticeAreasPage.js +176 -0
- package/dist/proserviceworld/pages/PracticeAreasPage.js.map +1 -0
- package/dist/proserviceworld/pages/TimePage.js +310 -0
- package/dist/proserviceworld/pages/TimePage.js.map +1 -0
- package/dist/proserviceworld/utils/cn.js +10 -0
- package/dist/proserviceworld/utils/cn.js.map +1 -0
- package/dist/proserviceworld/utils/nav.js +11 -0
- package/dist/proserviceworld/utils/nav.js.map +1 -0
- package/package.json +1 -1
- package/dist/proserviceworld/pages/AdminReportsPage.js +0 -579
- package/dist/proserviceworld/pages/AdminReportsPage.js.map +0 -1
- package/dist/proserviceworld/pages/AdminUsersPage.js +0 -468
- package/dist/proserviceworld/pages/AdminUsersPage.js.map +0 -1
- package/dist/proserviceworld/pages/BookingsPage.js +0 -446
- package/dist/proserviceworld/pages/BookingsPage.js.map +0 -1
- package/dist/proserviceworld/pages/MessagesPage.js +0 -238
- package/dist/proserviceworld/pages/MessagesPage.js.map +0 -1
- package/dist/proserviceworld/pages/PaymentsPage.js +0 -537
- package/dist/proserviceworld/pages/PaymentsPage.js.map +0 -1
- package/dist/proserviceworld/pages/ProjectsPage.js +0 -627
- package/dist/proserviceworld/pages/ProjectsPage.js.map +0 -1
- package/dist/proserviceworld/pages/ProviderDetailPage.js +0 -538
- package/dist/proserviceworld/pages/ProviderDetailPage.js.map +0 -1
- package/dist/proserviceworld/pages/ProvidersPage.js +0 -347
- package/dist/proserviceworld/pages/ProvidersPage.js.map +0 -1
- package/dist/proserviceworld/pages/ReviewsPage.js +0 -356
- package/dist/proserviceworld/pages/ReviewsPage.js.map +0 -1
- package/dist/proserviceworld/pages/ServiceDetailsPage.js +0 -631
- package/dist/proserviceworld/pages/ServiceDetailsPage.js.map +0 -1
- package/dist/proserviceworld/pages/ServicesPage.js +0 -344
- package/dist/proserviceworld/pages/ServicesPage.js.map +0 -1
- package/dist/proserviceworld/pages/VerificationPage.js +0 -370
- package/dist/proserviceworld/pages/VerificationPage.js.map +0 -1
- package/dist/proserviceworld/store/proserviceworldStore.js +0 -2490
- package/dist/proserviceworld/store/proserviceworldStore.js.map +0 -1
- package/dist/proserviceworld/utils/i18n.js +0 -15
- package/dist/proserviceworld/utils/i18n.js.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useMutation as e, useQuery as t, useQueryClient as n } from "@tanstack/react-query";
|
|
2
|
+
import { graphqlFetch as r } from "@burdenoff/fe-libs/shared/graphql";
|
|
3
|
+
import { clearGraphqlFetchResponseCache as i } from "@burdenoff/fe-libs/shared/graphql/fetch";
|
|
4
|
+
//#region src/proserviceworld/hooks/useEntityComments.ts
|
|
5
|
+
async function a(e, t) {
|
|
6
|
+
let n = await r({
|
|
7
|
+
gateway: "workspace",
|
|
8
|
+
query: e,
|
|
9
|
+
variables: t,
|
|
10
|
+
workspaceToken: !0
|
|
11
|
+
});
|
|
12
|
+
if (n.errors?.length) throw Error(n.errors[0]?.message ?? "Conversations request failed");
|
|
13
|
+
if (!n.data) throw Error("Conversations response did not include data");
|
|
14
|
+
return e.trimStart().startsWith("mutation") && i(), n.data;
|
|
15
|
+
}
|
|
16
|
+
var o = "id authorId content { text } createdAt", s = "proserviceworld-comments";
|
|
17
|
+
function c(e, n) {
|
|
18
|
+
return t({
|
|
19
|
+
queryKey: [
|
|
20
|
+
s,
|
|
21
|
+
e,
|
|
22
|
+
n
|
|
23
|
+
],
|
|
24
|
+
enabled: !!n,
|
|
25
|
+
queryFn: async () => (await a(`query PswGetComments($input: GetCommentsInput!) {
|
|
26
|
+
getEntityComments(input: $input) { items { ${o} } total }
|
|
27
|
+
}`, { input: {
|
|
28
|
+
entityType: e,
|
|
29
|
+
entityId: n,
|
|
30
|
+
take: 50,
|
|
31
|
+
sortBy: "createdAt",
|
|
32
|
+
sortOrder: "desc"
|
|
33
|
+
} })).getEntityComments
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function l(t, r) {
|
|
37
|
+
let i = n();
|
|
38
|
+
return e({
|
|
39
|
+
mutationFn: (e) => a(`mutation PswAddComment($input: CreateEntityCommentInput!) {
|
|
40
|
+
createEntityComment(input: $input) { ${o} }
|
|
41
|
+
}`, { input: {
|
|
42
|
+
entityType: t,
|
|
43
|
+
entityId: r,
|
|
44
|
+
content: { text: e }
|
|
45
|
+
} }),
|
|
46
|
+
onSuccess: () => i.invalidateQueries({ queryKey: [
|
|
47
|
+
s,
|
|
48
|
+
t,
|
|
49
|
+
r
|
|
50
|
+
] })
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { l as useAddEntityComment, c as useEntityComments };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=useEntityComments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEntityComments.js","names":[],"sources":["../../../src/proserviceworld/hooks/useEntityComments.ts"],"sourcesContent":["/**\n * Entity discussion via wspace-conversations-svc (NO duplication).\n * @module proserviceworld/hooks\n *\n * ProServiceWorld does NOT own a comments table. Discussion/notes on a client,\n * engagement or matter reuse the shared `wspace-conversations` entity-comment\n * API (createEntityComment / getEntityComments) — the same service that powers\n * comments everywhere on the platform — via the MFE's proven graphqlFetch\n * transport. `entityType` namespaces threads to this product\n * (\"proserviceworld-<entity>\"); `entityId` is the Psw row id.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\n\nasync function convQuery<TData>(query: string, variables: Record<string, unknown>): Promise<TData> {\n const response = await graphqlFetch<TData>({ gateway: 'workspace', query, variables, workspaceToken: true });\n if (response.errors?.length) throw new Error(response.errors[0]?.message ?? 'Conversations request failed');\n if (!response.data) throw new Error('Conversations response did not include data');\n if (query.trimStart().startsWith('mutation')) clearGraphqlFetchResponseCache();\n return response.data;\n}\n\nexport interface EntityComment {\n id: string;\n authorId: string;\n content: { text: string | null } | null;\n createdAt: string;\n}\n\nconst COMMENT_F = 'id authorId content { text } createdAt';\nconst QK = 'proserviceworld-comments' as const;\n\n/** List the discussion thread for a Psw entity (most recent first). */\nexport function useEntityComments(entityType: string, entityId: string | null) {\n return useQuery({\n queryKey: [QK, entityType, entityId],\n enabled: Boolean(entityId),\n queryFn: async () => {\n const data = await convQuery<{ getEntityComments: { items: EntityComment[]; total: number } }>(\n `query PswGetComments($input: GetCommentsInput!) {\n getEntityComments(input: $input) { items { ${COMMENT_F} } total }\n }`,\n { input: { entityType, entityId, take: 50, sortBy: 'createdAt', sortOrder: 'desc' } }\n );\n return data.getEntityComments;\n },\n });\n}\n\n/** Post a plain-text note onto a Psw entity's shared discussion thread. */\nexport function useAddEntityComment(entityType: string, entityId: string) {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (text: string) =>\n convQuery(\n `mutation PswAddComment($input: CreateEntityCommentInput!) {\n createEntityComment(input: $input) { ${COMMENT_F} }\n }`,\n { input: { entityType, entityId, content: { text } } }\n ),\n onSuccess: () => qc.invalidateQueries({ queryKey: [QK, entityType, entityId] }),\n });\n}\n"],"mappings":";;;;AAiBA,eAAe,EAAiB,GAAe,GAAoD;CACjG,IAAM,IAAW,MAAM,EAAoB;EAAE,SAAS;EAAa;EAAO;EAAW,gBAAgB;EAAM,CAAC;AAC5G,KAAI,EAAS,QAAQ,OAAQ,OAAU,MAAM,EAAS,OAAO,IAAI,WAAW,+BAA+B;AAC3G,KAAI,CAAC,EAAS,KAAM,OAAU,MAAM,8CAA8C;AAElF,QADI,EAAM,WAAW,CAAC,WAAW,WAAW,IAAE,GAAgC,EACvE,EAAS;;AAUlB,IAAM,IAAY,0CACZ,IAAK;AAGX,SAAgB,EAAkB,GAAoB,GAAyB;AAC7E,QAAO,EAAS;EACd,UAAU;GAAC;GAAI;GAAY;GAAS;EACpC,SAAS,EAAQ;EACjB,SAAS,aACM,MAAM,EACjB;uDAC+C,EAAU;YAEzD,EAAE,OAAO;GAAE;GAAY;GAAU,MAAM;GAAI,QAAQ;GAAa,WAAW;GAAQ,EAAE,CACtF,EACW;EAEf,CAAC;;AAIJ,SAAgB,EAAoB,GAAoB,GAAkB;CACxE,IAAM,IAAK,GAAgB;AAC3B,QAAO,EAAY;EACjB,aAAa,MACX,EACE;iDACyC,EAAU;YAEnD,EAAE,OAAO;GAAE;GAAY;GAAU,SAAS,EAAE,SAAM;GAAE,EAAE,CACvD;EACH,iBAAiB,EAAG,kBAAkB,EAAE,UAAU;GAAC;GAAI;GAAY;GAAS,EAAE,CAAC;EAChF,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { graphqlFetch as e } from "@burdenoff/fe-libs/shared/graphql";
|
|
2
|
+
//#region src/proserviceworld/hooks/useFiles.ts
|
|
3
|
+
var t = 21600, n = "/ProServiceWorld/Documents";
|
|
4
|
+
async function r(t, n) {
|
|
5
|
+
let r = await e({
|
|
6
|
+
gateway: "workspace",
|
|
7
|
+
query: t,
|
|
8
|
+
variables: n,
|
|
9
|
+
workspaceToken: !0
|
|
10
|
+
});
|
|
11
|
+
if (r.errors?.length) throw Error(r.errors[0]?.message ?? "Files request failed");
|
|
12
|
+
if (!r.data) throw Error("Files response did not include data");
|
|
13
|
+
return r.data;
|
|
14
|
+
}
|
|
15
|
+
async function i(e) {
|
|
16
|
+
await r("mutation PswEnsureFolder($path: String!) { ensureFolderByPath(path: $path) { id } }", { path: n });
|
|
17
|
+
let t = await r("mutation PswInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) { uploadUrl session { id } }\n }", { input: {
|
|
18
|
+
fileName: e.name,
|
|
19
|
+
mimeType: e.type || "application/octet-stream",
|
|
20
|
+
folderPath: n
|
|
21
|
+
} }), i = await fetch(t.initiateUpload.uploadUrl, {
|
|
22
|
+
method: "PUT",
|
|
23
|
+
body: e,
|
|
24
|
+
headers: { "Content-Type": e.type || "application/octet-stream" }
|
|
25
|
+
});
|
|
26
|
+
if (!i.ok) throw Error(`Upload failed (${i.status})`);
|
|
27
|
+
let a = await r("mutation PswCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) { fileId file { id name } }\n }", { input: {
|
|
28
|
+
sessionId: t.initiateUpload.session.id,
|
|
29
|
+
fileSize: String(e.size)
|
|
30
|
+
} });
|
|
31
|
+
return {
|
|
32
|
+
fileId: a.completeUpload.fileId,
|
|
33
|
+
name: a.completeUpload.file.name
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function a(e) {
|
|
37
|
+
return (await r("query PswGetFileDownloadUrl($id: ID!, $expiresIn: Int) { getFileDownloadUrl(id: $id, expiresIn: $expiresIn) }", {
|
|
38
|
+
id: e,
|
|
39
|
+
expiresIn: t
|
|
40
|
+
})).getFileDownloadUrl;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { a as getDocumentDownloadUrl, i as uploadDocumentFile };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=useFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFiles.js","names":[],"sources":["../../../src/proserviceworld/hooks/useFiles.ts"],"sourcesContent":["/**\n * File upload/download via wspace-files-svc (NO duplication).\n * @module proserviceworld/hooks\n *\n * ProServiceWorld never stores blobs. A PswDocument references a wspace-files\n * File by id; the Files service owns storage, signed URLs, and download audit.\n * Upload drives the SAME `graphqlFetch` workspace transport the rest of this\n * MFE uses, through the files 3-step presigned flow:\n * ensureFolderByPath -> initiateUpload -> HTTP PUT -> completeUpload\n * (completeUpload requires `fileSize` — omitting it fails every upload after the\n * S3 PUT). Display resolves a file id to a short-lived presigned URL.\n */\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\n/** Six hours — wspace-files rejects any expiresIn above the S3 7-day cap. */\nconst DOWNLOAD_URL_TTL_SECONDS = 21_600;\nconst DOCS_FOLDER = '/ProServiceWorld/Documents';\n\nasync function filesFetch<TData>(\n query: string,\n variables: Record<string, unknown>\n): Promise<TData> {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n query,\n variables,\n workspaceToken: true,\n });\n if (response.errors?.length)\n throw new Error(response.errors[0]?.message ?? 'Files request failed');\n if (!response.data) throw new Error('Files response did not include data');\n return response.data;\n}\n\n/**\n * Upload a browser File to wspace-files and return its file id. The caller\n * stores the id on a PswDocument via pswCreateDocument (metadata only).\n */\nexport async function uploadDocumentFile(file: File): Promise<{ fileId: string; name: string }> {\n await filesFetch<{ ensureFolderByPath: { id: string } }>(\n `mutation PswEnsureFolder($path: String!) { ensureFolderByPath(path: $path) { id } }`,\n { path: DOCS_FOLDER }\n );\n\n const initiated = await filesFetch<{\n initiateUpload: { uploadUrl: string; session: { id: string } };\n }>(\n `mutation PswInitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) { uploadUrl session { id } }\n }`,\n {\n input: {\n fileName: file.name,\n mimeType: file.type || 'application/octet-stream',\n folderPath: DOCS_FOLDER,\n },\n }\n );\n\n const putRes = await fetch(initiated.initiateUpload.uploadUrl, {\n method: 'PUT',\n body: file,\n headers: { 'Content-Type': file.type || 'application/octet-stream' },\n });\n if (!putRes.ok) throw new Error(`Upload failed (${putRes.status})`);\n\n const completed = await filesFetch<{\n completeUpload: { fileId: string; file: { id: string; name: string } };\n }>(\n `mutation PswCompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) { fileId file { id name } }\n }`,\n { input: { sessionId: initiated.initiateUpload.session.id, fileSize: String(file.size) } }\n );\n\n return { fileId: completed.completeUpload.fileId, name: completed.completeUpload.file.name };\n}\n\n/** Resolve a wspace-files file id to a short-lived presigned download URL. */\nexport async function getDocumentDownloadUrl(fileId: string): Promise<string> {\n const data = await filesFetch<{ getFileDownloadUrl: string }>(\n `query PswGetFileDownloadUrl($id: ID!, $expiresIn: Int) { getFileDownloadUrl(id: $id, expiresIn: $expiresIn) }`,\n { id: fileId, expiresIn: DOWNLOAD_URL_TTL_SECONDS }\n );\n return data.getFileDownloadUrl;\n}\n"],"mappings":";;AAgBA,IAAM,IAA2B,OAC3B,IAAc;AAEpB,eAAe,EACb,GACA,GACgB;CAChB,IAAM,IAAW,MAAM,EAAoB;EACzC,SAAS;EACT;EACA;EACA,gBAAgB;EACjB,CAAC;AACF,KAAI,EAAS,QAAQ,OACnB,OAAU,MAAM,EAAS,OAAO,IAAI,WAAW,uBAAuB;AACxE,KAAI,CAAC,EAAS,KAAM,OAAU,MAAM,sCAAsC;AAC1E,QAAO,EAAS;;AAOlB,eAAsB,EAAmB,GAAuD;AAC9F,OAAM,EACJ,uFACA,EAAE,MAAM,GAAa,CACtB;CAED,IAAM,IAAY,MAAM,EAGtB,uIAGA,EACE,OAAO;EACL,UAAU,EAAK;EACf,UAAU,EAAK,QAAQ;EACvB,YAAY;EACb,EACF,CACF,EAEK,IAAS,MAAM,MAAM,EAAU,eAAe,WAAW;EAC7D,QAAQ;EACR,MAAM;EACN,SAAS,EAAE,gBAAgB,EAAK,QAAQ,4BAA4B;EACrE,CAAC;AACF,KAAI,CAAC,EAAO,GAAI,OAAU,MAAM,kBAAkB,EAAO,OAAO,GAAG;CAEnE,IAAM,IAAY,MAAM,EAGtB,sIAGA,EAAE,OAAO;EAAE,WAAW,EAAU,eAAe,QAAQ;EAAI,UAAU,OAAO,EAAK,KAAK;EAAE,EAAE,CAC3F;AAED,QAAO;EAAE,QAAQ,EAAU,eAAe;EAAQ,MAAM,EAAU,eAAe,KAAK;EAAM;;AAI9F,eAAsB,EAAuB,GAAiC;AAK5E,SAJa,MAAM,EACjB,iHACA;EAAE,IAAI;EAAQ,WAAW;EAA0B,CACpD,EACW"}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { useMutation as e, useQuery as t, useQueryClient as n } from "@tanstack/react-query";
|
|
2
|
+
import { graphqlFetch as r } from "@burdenoff/fe-libs/shared/graphql";
|
|
3
|
+
import { clearGraphqlFetchResponseCache as i } from "@burdenoff/fe-libs/shared/graphql/fetch";
|
|
4
|
+
//#region src/proserviceworld/hooks/useProServiceWorldApi.ts
|
|
5
|
+
async function a(e, t = {}) {
|
|
6
|
+
let n = await r({
|
|
7
|
+
gateway: "workspace",
|
|
8
|
+
query: e,
|
|
9
|
+
variables: t,
|
|
10
|
+
workspaceToken: !0
|
|
11
|
+
});
|
|
12
|
+
if (n.errors?.length) throw Error(n.errors[0]?.message ?? "GraphQL request failed");
|
|
13
|
+
if (!n.data) throw Error("GraphQL response did not include data");
|
|
14
|
+
return e.trimStart().startsWith("mutation") && i(), n.data;
|
|
15
|
+
}
|
|
16
|
+
var o = "proserviceworld";
|
|
17
|
+
function s(e, ...t) {
|
|
18
|
+
for (let n of t) e.invalidateQueries({ queryKey: [o, n] });
|
|
19
|
+
}
|
|
20
|
+
var c = "\n id name type status industry contactName contactEmail contactPhone address\n relationshipOwnerId notes tags createdAt updatedAt", l = "\n id clientId practiceAreaId name description status feeArrangement feeAmount currency\n startDate endDate responsiblePartnerId tags createdAt updatedAt client { id name }", u = "id engagementId name description status version acceptanceCriteria dueDate acceptedAt createdAt", d = "id engagementId name description status dueDate completedAt triggerAmount triggersInvoice createdAt", f = "\n id clientId engagementId practiceAreaId reference title description status priority isPrivileged\n dueDate closedAt leadPractitionerId tags createdAt updatedAt client { id name }", p = "id engagementId matterId practitionerId date minutes billable rate narrative status invoiceId createdAt", m = "id clientId engagementId number status currency subtotal taxAmount total issueDate dueDate paidAt notes createdAt", h = "id type status subjectType subjectId title details reviewerId dueDate resolvedAt createdAt", g = "id clientId matterId status searchedParties findings waiverReason resolvedAt createdAt", _ = "id name code description isActive createdAt", v = "id name description status classification version legalHold retainUntil matterId engagementId tags file { id } createdAt";
|
|
21
|
+
function y() {
|
|
22
|
+
return t({
|
|
23
|
+
queryKey: [o, "dashboard"],
|
|
24
|
+
queryFn: async () => (await a("\n query PswDashboard {\n pswDashboardStats {\n totalClients activeClients activeEngagements openMatters\n outstandingInvoiceTotal paidInvoiceTotal unbilledHours billedHours\n pendingComplianceChecks openConflictChecks\n engagementsByStatus { status count }\n invoicesByStatus { status count }\n mattersByStatus { status count }\n revenueByMonth { month amount }\n }\n }")).pswDashboardStats
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function b(e = {}) {
|
|
28
|
+
return t({
|
|
29
|
+
queryKey: [
|
|
30
|
+
o,
|
|
31
|
+
"clients",
|
|
32
|
+
e
|
|
33
|
+
],
|
|
34
|
+
queryFn: async () => (await a(`query PswClients($status: PswClientStatus, $search: String, $pagination: PaginationInput) {
|
|
35
|
+
pswListClients(status: $status, search: $search, pagination: $pagination) {
|
|
36
|
+
items { ${c} } pageInfo { hasMore cursor } totalCount
|
|
37
|
+
}
|
|
38
|
+
}`, {
|
|
39
|
+
status: e.status ?? null,
|
|
40
|
+
search: e.search ?? null,
|
|
41
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
42
|
+
})).pswListClients
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function x(e) {
|
|
46
|
+
return t({
|
|
47
|
+
queryKey: [
|
|
48
|
+
o,
|
|
49
|
+
"client",
|
|
50
|
+
e
|
|
51
|
+
],
|
|
52
|
+
enabled: !!e,
|
|
53
|
+
queryFn: async () => (await a(`query PswClient($id: ID!) {
|
|
54
|
+
pswClient(id: $id) {
|
|
55
|
+
${c}
|
|
56
|
+
engagements { ${l} }
|
|
57
|
+
matters { ${f} }
|
|
58
|
+
}
|
|
59
|
+
}`, { id: e })).pswClient
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function S() {
|
|
63
|
+
let t = n();
|
|
64
|
+
return e({
|
|
65
|
+
mutationFn: (e) => a(`mutation PswCreateClient($input: PswCreateClientInput!) { pswCreateClient(input: $input) { ${c} } }`, { input: e }),
|
|
66
|
+
onSuccess: () => s(t, "clients", "dashboard")
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function C() {
|
|
70
|
+
let t = n();
|
|
71
|
+
return e({
|
|
72
|
+
mutationFn: (e) => a(`mutation PswUpdateClient($id: ID!, $input: PswUpdateClientInput!) { pswUpdateClient(id: $id, input: $input) { ${c} } }`, e),
|
|
73
|
+
onSuccess: (e, n) => {
|
|
74
|
+
s(t, "clients", "dashboard"), t.invalidateQueries({ queryKey: [
|
|
75
|
+
o,
|
|
76
|
+
"client",
|
|
77
|
+
n.id
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function w() {
|
|
83
|
+
let t = n();
|
|
84
|
+
return e({
|
|
85
|
+
mutationFn: (e) => a("mutation PswArchiveClient($id: ID!) { pswArchiveClient(id: $id) }", { id: e }),
|
|
86
|
+
onSuccess: () => s(t, "clients", "dashboard")
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function T(e = {}) {
|
|
90
|
+
return t({
|
|
91
|
+
queryKey: [
|
|
92
|
+
o,
|
|
93
|
+
"engagements",
|
|
94
|
+
e
|
|
95
|
+
],
|
|
96
|
+
queryFn: async () => (await a(`query PswEngagements($clientId: ID, $status: PswEngagementStatus, $search: String, $pagination: PaginationInput) {
|
|
97
|
+
pswListEngagements(clientId: $clientId, status: $status, search: $search, pagination: $pagination) {
|
|
98
|
+
items { ${l} } pageInfo { hasMore cursor } totalCount
|
|
99
|
+
}
|
|
100
|
+
}`, {
|
|
101
|
+
clientId: e.clientId ?? null,
|
|
102
|
+
status: e.status ?? null,
|
|
103
|
+
search: e.search ?? null,
|
|
104
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
105
|
+
})).pswListEngagements
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function E(e) {
|
|
109
|
+
return t({
|
|
110
|
+
queryKey: [
|
|
111
|
+
o,
|
|
112
|
+
"engagement",
|
|
113
|
+
e
|
|
114
|
+
],
|
|
115
|
+
enabled: !!e,
|
|
116
|
+
queryFn: async () => (await a(`query PswEngagement($id: ID!) {
|
|
117
|
+
pswEngagement(id: $id) {
|
|
118
|
+
${l}
|
|
119
|
+
deliverables { ${u} }
|
|
120
|
+
milestones { ${d} }
|
|
121
|
+
}
|
|
122
|
+
}`, { id: e })).pswEngagement
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function D() {
|
|
126
|
+
let t = n();
|
|
127
|
+
return e({
|
|
128
|
+
mutationFn: (e) => a(`mutation PswCreateEngagement($input: PswCreateEngagementInput!) { pswCreateEngagement(input: $input) { ${l} } }`, { input: e }),
|
|
129
|
+
onSuccess: () => s(t, "engagements", "dashboard")
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function O() {
|
|
133
|
+
let t = n();
|
|
134
|
+
return e({
|
|
135
|
+
mutationFn: (e) => a(`mutation PswTransitionEngagement($id: ID!, $status: PswEngagementStatus!) { pswTransitionEngagement(id: $id, status: $status) { ${l} } }`, e),
|
|
136
|
+
onSuccess: (e, n) => {
|
|
137
|
+
s(t, "engagements", "dashboard"), t.invalidateQueries({ queryKey: [
|
|
138
|
+
o,
|
|
139
|
+
"engagement",
|
|
140
|
+
n.id
|
|
141
|
+
] });
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function k() {
|
|
146
|
+
let t = n();
|
|
147
|
+
return e({
|
|
148
|
+
mutationFn: (e) => a(`mutation PswCreateDeliverable($input: PswCreateDeliverableInput!) { pswCreateDeliverable(input: $input) { ${u} } }`, { input: e }),
|
|
149
|
+
onSuccess: (e, n) => t.invalidateQueries({ queryKey: [
|
|
150
|
+
o,
|
|
151
|
+
"engagement",
|
|
152
|
+
n.engagementId
|
|
153
|
+
] })
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function A() {
|
|
157
|
+
let t = n();
|
|
158
|
+
return e({
|
|
159
|
+
mutationFn: (e) => a(`mutation PswTransitionDeliverable($id: ID!, $status: PswDeliverableStatus!) { pswTransitionDeliverable(id: $id, status: $status) { ${u} } }`, {
|
|
160
|
+
id: e.id,
|
|
161
|
+
status: e.status
|
|
162
|
+
}),
|
|
163
|
+
onSuccess: (e, n) => t.invalidateQueries({ queryKey: [
|
|
164
|
+
o,
|
|
165
|
+
"engagement",
|
|
166
|
+
n.engagementId
|
|
167
|
+
] })
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function j() {
|
|
171
|
+
let t = n();
|
|
172
|
+
return e({
|
|
173
|
+
mutationFn: (e) => a(`mutation PswCreateMilestone($input: PswCreateMilestoneInput!) { pswCreateMilestone(input: $input) { ${d} } }`, { input: e }),
|
|
174
|
+
onSuccess: (e, n) => t.invalidateQueries({ queryKey: [
|
|
175
|
+
o,
|
|
176
|
+
"engagement",
|
|
177
|
+
n.engagementId
|
|
178
|
+
] })
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function M() {
|
|
182
|
+
let t = n();
|
|
183
|
+
return e({
|
|
184
|
+
mutationFn: (e) => a(`mutation PswCompleteMilestone($id: ID!) { pswCompleteMilestone(id: $id) { ${d} } }`, { id: e.id }),
|
|
185
|
+
onSuccess: (e, n) => t.invalidateQueries({ queryKey: [
|
|
186
|
+
o,
|
|
187
|
+
"engagement",
|
|
188
|
+
n.engagementId
|
|
189
|
+
] })
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function N(e = {}) {
|
|
193
|
+
return t({
|
|
194
|
+
queryKey: [
|
|
195
|
+
o,
|
|
196
|
+
"matters",
|
|
197
|
+
e
|
|
198
|
+
],
|
|
199
|
+
queryFn: async () => (await a(`query PswMatters($clientId: ID, $engagementId: ID, $status: PswMatterStatus, $search: String, $pagination: PaginationInput) {
|
|
200
|
+
pswListMatters(clientId: $clientId, engagementId: $engagementId, status: $status, search: $search, pagination: $pagination) {
|
|
201
|
+
items { ${f} } pageInfo { hasMore cursor } totalCount
|
|
202
|
+
}
|
|
203
|
+
}`, {
|
|
204
|
+
clientId: e.clientId ?? null,
|
|
205
|
+
engagementId: e.engagementId ?? null,
|
|
206
|
+
status: e.status ?? null,
|
|
207
|
+
search: e.search ?? null,
|
|
208
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
209
|
+
})).pswListMatters
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function ee() {
|
|
213
|
+
let t = n();
|
|
214
|
+
return e({
|
|
215
|
+
mutationFn: (e) => a(`mutation PswCreateMatter($input: PswCreateMatterInput!) { pswCreateMatter(input: $input) { ${f} } }`, { input: e }),
|
|
216
|
+
onSuccess: () => s(t, "matters", "dashboard")
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
function P() {
|
|
220
|
+
let t = n();
|
|
221
|
+
return e({
|
|
222
|
+
mutationFn: (e) => a(`mutation PswCloseMatter($id: ID!) { pswCloseMatter(id: $id) { ${f} } }`, { id: e }),
|
|
223
|
+
onSuccess: () => s(t, "matters", "dashboard")
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function F(e = {}) {
|
|
227
|
+
return t({
|
|
228
|
+
queryKey: [
|
|
229
|
+
o,
|
|
230
|
+
"time",
|
|
231
|
+
e
|
|
232
|
+
],
|
|
233
|
+
queryFn: async () => (await a(`query PswTimeEntries($engagementId: ID, $matterId: ID, $status: PswTimeEntryStatus, $billable: Boolean, $pagination: PaginationInput) {
|
|
234
|
+
pswListTimeEntries(engagementId: $engagementId, matterId: $matterId, status: $status, billable: $billable, pagination: $pagination) {
|
|
235
|
+
items { ${p} } pageInfo { hasMore cursor } totalCount
|
|
236
|
+
}
|
|
237
|
+
}`, {
|
|
238
|
+
engagementId: e.engagementId ?? null,
|
|
239
|
+
matterId: e.matterId ?? null,
|
|
240
|
+
status: e.status ?? null,
|
|
241
|
+
billable: e.billable ?? null,
|
|
242
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
243
|
+
})).pswListTimeEntries
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function I() {
|
|
247
|
+
let t = n();
|
|
248
|
+
return e({
|
|
249
|
+
mutationFn: (e) => a(`mutation PswLogTime($input: PswCreateTimeEntryInput!) { pswLogTimeEntry(input: $input) { ${p} } }`, { input: e }),
|
|
250
|
+
onSuccess: () => s(t, "time", "dashboard")
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
function L() {
|
|
254
|
+
let t = n();
|
|
255
|
+
return e({
|
|
256
|
+
mutationFn: (e) => a(`mutation PswSubmitTime($id: ID!) { pswSubmitTimeEntry(id: $id) { ${p} } }`, { id: e }),
|
|
257
|
+
onSuccess: () => s(t, "time")
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
function R() {
|
|
261
|
+
let t = n();
|
|
262
|
+
return e({
|
|
263
|
+
mutationFn: (e) => a(`mutation PswApproveTime($id: ID!) { pswApproveTimeEntry(id: $id) { ${p} } }`, { id: e }),
|
|
264
|
+
onSuccess: () => s(t, "time")
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
function z(e = {}) {
|
|
268
|
+
return t({
|
|
269
|
+
queryKey: [
|
|
270
|
+
o,
|
|
271
|
+
"invoices",
|
|
272
|
+
e
|
|
273
|
+
],
|
|
274
|
+
queryFn: async () => (await a(`query PswInvoices($clientId: ID, $status: PswInvoiceStatus, $pagination: PaginationInput) {
|
|
275
|
+
pswListInvoices(clientId: $clientId, status: $status, pagination: $pagination) {
|
|
276
|
+
items { ${m} } pageInfo { hasMore cursor } totalCount
|
|
277
|
+
}
|
|
278
|
+
}`, {
|
|
279
|
+
clientId: e.clientId ?? null,
|
|
280
|
+
status: e.status ?? null,
|
|
281
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
282
|
+
})).pswListInvoices
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
function B() {
|
|
286
|
+
let t = n();
|
|
287
|
+
return e({
|
|
288
|
+
mutationFn: (e) => a(`mutation PswCreateInvoice($input: PswCreateInvoiceInput!) { pswCreateInvoice(input: $input) { ${m} } }`, { input: e }),
|
|
289
|
+
onSuccess: () => s(t, "invoices", "dashboard")
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
function V() {
|
|
293
|
+
let t = n();
|
|
294
|
+
return e({
|
|
295
|
+
mutationFn: (e) => a(`mutation PswMarkPaid($id: ID!) { pswMarkInvoicePaid(id: $id) { ${m} } }`, { id: e }),
|
|
296
|
+
onSuccess: () => s(t, "invoices", "dashboard")
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function H(e = {}) {
|
|
300
|
+
return t({
|
|
301
|
+
queryKey: [
|
|
302
|
+
o,
|
|
303
|
+
"compliance",
|
|
304
|
+
e
|
|
305
|
+
],
|
|
306
|
+
queryFn: async () => (await a(`query PswCompliance($status: PswComplianceStatus, $pagination: PaginationInput) {
|
|
307
|
+
pswListComplianceChecks(status: $status, pagination: $pagination) { ${h} }
|
|
308
|
+
}`, {
|
|
309
|
+
status: e.status ?? null,
|
|
310
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
311
|
+
})).pswListComplianceChecks
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function U() {
|
|
315
|
+
let t = n();
|
|
316
|
+
return e({
|
|
317
|
+
mutationFn: (e) => a(`mutation PswCreateCompliance($input: PswCreateComplianceCheckInput!) { pswCreateComplianceCheck(input: $input) { ${h} } }`, { input: e }),
|
|
318
|
+
onSuccess: () => s(t, "compliance", "dashboard")
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function W() {
|
|
322
|
+
let t = n();
|
|
323
|
+
return e({
|
|
324
|
+
mutationFn: (e) => a(`mutation PswResolveCompliance($id: ID!, $status: PswComplianceStatus!, $details: String) { pswResolveComplianceCheck(id: $id, status: $status, details: $details) { ${h} } }`, e),
|
|
325
|
+
onSuccess: () => s(t, "compliance", "dashboard")
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
function G(e = {}) {
|
|
329
|
+
return t({
|
|
330
|
+
queryKey: [
|
|
331
|
+
o,
|
|
332
|
+
"conflicts",
|
|
333
|
+
e
|
|
334
|
+
],
|
|
335
|
+
queryFn: async () => (await a(`query PswConflicts($clientId: ID, $pagination: PaginationInput) {
|
|
336
|
+
pswListConflictChecks(clientId: $clientId, pagination: $pagination) { ${g} }
|
|
337
|
+
}`, {
|
|
338
|
+
clientId: e.clientId ?? null,
|
|
339
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
340
|
+
})).pswListConflictChecks
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
function K() {
|
|
344
|
+
let t = n();
|
|
345
|
+
return e({
|
|
346
|
+
mutationFn: (e) => a(`mutation PswCreateConflict($input: PswCreateConflictCheckInput!) { pswCreateConflictCheck(input: $input) { ${g} } }`, { input: e }),
|
|
347
|
+
onSuccess: () => s(t, "conflicts", "dashboard")
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function q() {
|
|
351
|
+
let t = n();
|
|
352
|
+
return e({
|
|
353
|
+
mutationFn: (e) => a(`mutation PswResolveConflict($id: ID!, $status: PswConflictCheckStatus!, $findings: String, $waiverReason: String) {
|
|
354
|
+
pswResolveConflictCheck(id: $id, status: $status, findings: $findings, waiverReason: $waiverReason) { ${g} }
|
|
355
|
+
}`, e),
|
|
356
|
+
onSuccess: () => s(t, "conflicts", "dashboard")
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function J() {
|
|
360
|
+
return t({
|
|
361
|
+
queryKey: [o, "practiceAreas"],
|
|
362
|
+
queryFn: async () => (await a(`query PswPracticeAreas { pswListPracticeAreas(pagination: { limit: 100 }) { ${_} } }`)).pswListPracticeAreas
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
function Y() {
|
|
366
|
+
let t = n();
|
|
367
|
+
return e({
|
|
368
|
+
mutationFn: (e) => a(`mutation PswCreatePracticeArea($input: PswCreatePracticeAreaInput!) { pswCreatePracticeArea(input: $input) { ${_} } }`, { input: e }),
|
|
369
|
+
onSuccess: () => s(t, "practiceAreas")
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
function X() {
|
|
373
|
+
let t = n();
|
|
374
|
+
return e({
|
|
375
|
+
mutationFn: (e) => a(`mutation PswUpdatePracticeArea($id: ID!, $input: PswUpdatePracticeAreaInput!) { pswUpdatePracticeArea(id: $id, input: $input) { ${_} } }`, e),
|
|
376
|
+
onSuccess: () => s(t, "practiceAreas")
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
function Z(e = {}) {
|
|
380
|
+
return t({
|
|
381
|
+
queryKey: [
|
|
382
|
+
o,
|
|
383
|
+
"documents",
|
|
384
|
+
e
|
|
385
|
+
],
|
|
386
|
+
queryFn: async () => (await a(`query PswDocuments($engagementId: ID, $matterId: ID, $classification: PswDocumentClassification, $status: PswDocumentStatus, $pagination: PaginationInput) {
|
|
387
|
+
pswListDocuments(engagementId: $engagementId, matterId: $matterId, classification: $classification, status: $status, pagination: $pagination) {
|
|
388
|
+
items { ${v} } pageInfo { hasMore cursor } totalCount
|
|
389
|
+
}
|
|
390
|
+
}`, {
|
|
391
|
+
engagementId: e.engagementId ?? null,
|
|
392
|
+
matterId: e.matterId ?? null,
|
|
393
|
+
classification: e.classification ?? null,
|
|
394
|
+
status: e.status ?? null,
|
|
395
|
+
pagination: e.pagination ?? { limit: 100 }
|
|
396
|
+
})).pswListDocuments
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
function Q() {
|
|
400
|
+
let t = n();
|
|
401
|
+
return e({
|
|
402
|
+
mutationFn: (e) => a(`mutation PswCreateDocument($input: PswCreateDocumentInput!) { pswCreateDocument(input: $input) { ${v} } }`, { input: e }),
|
|
403
|
+
onSuccess: () => s(t, "documents")
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
function $() {
|
|
407
|
+
let t = n();
|
|
408
|
+
return e({
|
|
409
|
+
mutationFn: (e) => a(`mutation PswArchiveDocument($id: ID!) { pswArchiveDocument(id: $id) { ${v} } }`, { id: e }),
|
|
410
|
+
onSuccess: () => s(t, "documents")
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
//#endregion
|
|
414
|
+
export { R as useApproveTimeEntry, w as useArchiveClient, $ as useArchiveDocument, x as useClient, b as useClients, P as useCloseMatter, M as useCompleteMilestone, H as useComplianceChecks, G as useConflictChecks, S as useCreateClient, U as useCreateComplianceCheck, K as useCreateConflictCheck, k as useCreateDeliverable, Q as useCreateDocument, D as useCreateEngagement, B as useCreateInvoice, ee as useCreateMatter, j as useCreateMilestone, Y as useCreatePracticeArea, y as useDashboardStats, Z as useDocuments, E as useEngagement, T as useEngagements, z as useInvoices, I as useLogTimeEntry, V as useMarkInvoicePaid, N as useMatters, J as usePracticeAreas, W as useResolveComplianceCheck, q as useResolveConflictCheck, L as useSubmitTimeEntry, F as useTimeEntries, A as useTransitionDeliverable, O as useTransitionEngagement, C as useUpdateClient, X as useUpdatePracticeArea };
|
|
415
|
+
|
|
416
|
+
//# sourceMappingURL=useProServiceWorldApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useProServiceWorldApi.js","names":[],"sources":["../../../src/proserviceworld/hooks/useProServiceWorldApi.ts"],"sourcesContent":["/**\n * ProServiceWorld API hooks\n * @module proserviceworld/hooks\n *\n * Real data layer for the ProServiceWorld workspace subgraph (`proserviceworld`\n * Hive service / `wspace-proserviceworld-svc`). Every hook talks to the live\n * workspace GraphQL gateway via {@link graphqlFetch} with inline operations\n * whose fields mirror `.hive-schema.graphql` exactly. No mocks.\n *\n * Conventions (mirror microfe-hookmovies / microfe-collabkin):\n * - `pswQuery` wraps graphqlFetch({ gateway: 'workspace', workspaceToken: true })\n * and throws on GraphQL errors / missing data.\n * - One react-query `useQuery` per read op and `useMutation` per write op.\n * - Strict hand-written result interfaces — no `any`.\n * - Lists paginate by offset (the workspaces gateway strips the cursor arg);\n * `*Connection { items, pageInfo { hasMore cursor }, totalCount }` verbatim.\n * - After any successful mutation we clear fe-libs' short-lived graphqlFetch\n * read cache so the very next refetch is fresh (fleet stale-read fix).\n */\n\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query';\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\n\n// ============================================================================\n// Low-level runner\n// ============================================================================\n\nasync function pswQuery<TData>(\n query: string,\n variables: Record<string, unknown> = {}\n): Promise<TData> {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n query,\n variables,\n workspaceToken: true,\n });\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n if (query.trimStart().startsWith('mutation')) {\n clearGraphqlFetchResponseCache();\n }\n return response.data;\n}\n\nconst QK = 'proserviceworld' as const;\n\n/** Invalidate a set of top-level query keys after a write. */\nfunction invalidate(qc: QueryClient, ...keys: string[]): void {\n for (const key of keys) void qc.invalidateQueries({ queryKey: [QK, key] });\n}\n\n// ============================================================================\n// Shared types (mirror .hive-schema.graphql)\n// ============================================================================\n\nexport interface PswPagination {\n limit?: number;\n offset?: number;\n}\nexport interface PswPageInfo {\n hasMore: boolean;\n cursor: string | null;\n}\nexport interface PswConnection<T> {\n items: T[];\n pageInfo: PswPageInfo;\n totalCount: number;\n}\n\nexport type PswClientType = 'INDIVIDUAL' | 'ORGANIZATION';\nexport type PswClientStatus = 'PROSPECT' | 'ACTIVE' | 'INACTIVE' | 'ARCHIVED';\nexport type PswFeeArrangement = 'FIXED' | 'HOURLY' | 'RETAINER' | 'VALUE_BASED';\nexport type PswEngagementStatus =\n | 'PROPOSAL'\n | 'ACCEPTED'\n | 'IN_PROGRESS'\n | 'REVIEW'\n | 'DELIVERED'\n | 'INVOICED'\n | 'CLOSED'\n | 'CANCELLED';\nexport type PswMatterStatus = 'OPEN' | 'ON_HOLD' | 'CLOSED' | 'ARCHIVED';\nexport type PswMatterPriority = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';\nexport type PswDeliverableStatus =\n | 'DRAFT'\n | 'INTERNAL_REVIEW'\n | 'CLIENT_REVIEW'\n | 'ACCEPTED'\n | 'REJECTED';\nexport type PswMilestoneStatus = 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED';\nexport type PswDocumentStatus = 'DRAFT' | 'FINAL' | 'ARCHIVED';\nexport type PswDocumentClassification = 'PUBLIC' | 'INTERNAL' | 'CONFIDENTIAL' | 'PRIVILEGED';\nexport type PswTimeEntryStatus = 'DRAFT' | 'SUBMITTED' | 'APPROVED' | 'REJECTED' | 'BILLED';\nexport type PswInvoiceStatus = 'DRAFT' | 'SENT' | 'PAID' | 'OVERDUE' | 'CANCELLED';\nexport type PswComplianceType =\n | 'ENGAGEMENT_ACCEPTANCE'\n | 'INDEPENDENCE'\n | 'LICENSING'\n | 'CONTINUING_EDUCATION'\n | 'DATA_RETENTION'\n | 'LEGAL_HOLD';\nexport type PswComplianceStatus = 'PENDING' | 'IN_REVIEW' | 'PASSED' | 'FAILED' | 'WAIVED';\nexport type PswConflictCheckStatus =\n | 'PENDING'\n | 'CLEAR'\n | 'POTENTIAL_CONFLICT'\n | 'CONFLICT'\n | 'WAIVED';\nexport type PswTeamRole = 'PARTNER' | 'MANAGER' | 'ASSOCIATE' | 'SPECIALIST' | 'SUPPORT';\n\nexport interface PswClient {\n id: string;\n name: string;\n type: PswClientType;\n status: PswClientStatus;\n industry: string | null;\n contactName: string | null;\n contactEmail: string | null;\n contactPhone: string | null;\n address: string | null;\n relationshipOwnerId: string | null;\n notes: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n}\nexport interface PswClientDetail extends PswClient {\n engagements: PswEngagement[];\n matters: PswMatter[];\n}\nexport interface PswEngagement {\n id: string;\n clientId: string;\n practiceAreaId: string | null;\n name: string;\n description: string | null;\n status: PswEngagementStatus;\n feeArrangement: PswFeeArrangement;\n feeAmount: number;\n currency: string;\n startDate: string | null;\n endDate: string | null;\n responsiblePartnerId: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n client?: { id: string; name: string } | null;\n}\nexport interface PswDeliverable {\n id: string;\n engagementId: string;\n name: string;\n description: string | null;\n status: PswDeliverableStatus;\n version: number;\n acceptanceCriteria: string | null;\n dueDate: string | null;\n acceptedAt: string | null;\n createdAt: string;\n}\nexport interface PswMilestone {\n id: string;\n engagementId: string;\n name: string;\n description: string | null;\n status: PswMilestoneStatus;\n dueDate: string | null;\n completedAt: string | null;\n triggerAmount: number;\n triggersInvoice: boolean;\n createdAt: string;\n}\nexport interface PswEngagementDetail extends PswEngagement {\n deliverables: PswDeliverable[];\n milestones: PswMilestone[];\n}\nexport interface PswMatter {\n id: string;\n clientId: string;\n engagementId: string | null;\n practiceAreaId: string | null;\n reference: string | null;\n title: string;\n description: string | null;\n status: PswMatterStatus;\n priority: PswMatterPriority;\n isPrivileged: boolean;\n dueDate: string | null;\n closedAt: string | null;\n leadPractitionerId: string | null;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n client?: { id: string; name: string } | null;\n}\nexport interface PswTimeEntry {\n id: string;\n engagementId: string | null;\n matterId: string | null;\n practitionerId: string;\n date: string;\n minutes: number;\n billable: boolean;\n rate: number;\n narrative: string | null;\n status: PswTimeEntryStatus;\n invoiceId: string | null;\n createdAt: string;\n}\nexport interface PswInvoice {\n id: string;\n clientId: string;\n engagementId: string | null;\n number: string;\n status: PswInvoiceStatus;\n currency: string;\n subtotal: number;\n taxAmount: number;\n total: number;\n issueDate: string | null;\n dueDate: string | null;\n paidAt: string | null;\n notes: string | null;\n createdAt: string;\n}\nexport interface PswComplianceCheck {\n id: string;\n type: PswComplianceType;\n status: PswComplianceStatus;\n subjectType: string;\n subjectId: string;\n title: string;\n details: string | null;\n reviewerId: string | null;\n dueDate: string | null;\n resolvedAt: string | null;\n createdAt: string;\n}\nexport interface PswConflictCheck {\n id: string;\n clientId: string;\n matterId: string | null;\n status: PswConflictCheckStatus;\n searchedParties: string[];\n findings: string | null;\n waiverReason: string | null;\n resolvedAt: string | null;\n createdAt: string;\n}\nexport interface PswPracticeArea {\n id: string;\n name: string;\n code: string | null;\n description: string | null;\n isActive: boolean;\n createdAt: string;\n}\nexport interface PswDocument {\n id: string;\n name: string;\n description: string | null;\n status: PswDocumentStatus;\n classification: PswDocumentClassification;\n version: number;\n legalHold: boolean;\n retainUntil: string | null;\n matterId: string | null;\n engagementId: string | null;\n tags: string[];\n file: { id: string } | null;\n createdAt: string;\n}\nexport interface PswStatusCount {\n status: string;\n count: number;\n}\nexport interface PswMonthlyAmount {\n month: string;\n amount: number;\n}\nexport interface PswDashboardStats {\n totalClients: number;\n activeClients: number;\n activeEngagements: number;\n openMatters: number;\n outstandingInvoiceTotal: number;\n paidInvoiceTotal: number;\n unbilledHours: number;\n billedHours: number;\n pendingComplianceChecks: number;\n openConflictChecks: number;\n engagementsByStatus: PswStatusCount[];\n invoicesByStatus: PswStatusCount[];\n mattersByStatus: PswStatusCount[];\n revenueByMonth: PswMonthlyAmount[];\n}\n\n// ============================================================================\n// GraphQL fragments\n// ============================================================================\n\nconst CLIENT_F = `\n id name type status industry contactName contactEmail contactPhone address\n relationshipOwnerId notes tags createdAt updatedAt`;\nconst ENGAGEMENT_F = `\n id clientId practiceAreaId name description status feeArrangement feeAmount currency\n startDate endDate responsiblePartnerId tags createdAt updatedAt client { id name }`;\nconst DELIVERABLE_F = `id engagementId name description status version acceptanceCriteria dueDate acceptedAt createdAt`;\nconst MILESTONE_F = `id engagementId name description status dueDate completedAt triggerAmount triggersInvoice createdAt`;\nconst MATTER_F = `\n id clientId engagementId practiceAreaId reference title description status priority isPrivileged\n dueDate closedAt leadPractitionerId tags createdAt updatedAt client { id name }`;\nconst TIME_F = `id engagementId matterId practitionerId date minutes billable rate narrative status invoiceId createdAt`;\nconst INVOICE_F = `id clientId engagementId number status currency subtotal taxAmount total issueDate dueDate paidAt notes createdAt`;\nconst COMPLIANCE_F = `id type status subjectType subjectId title details reviewerId dueDate resolvedAt createdAt`;\nconst CONFLICT_F = `id clientId matterId status searchedParties findings waiverReason resolvedAt createdAt`;\nconst PRACTICE_AREA_F = `id name code description isActive createdAt`;\nconst DOCUMENT_F = `id name description status classification version legalHold retainUntil matterId engagementId tags file { id } createdAt`;\n\n// ============================================================================\n// Dashboard\n// ============================================================================\n\nexport function useDashboardStats() {\n return useQuery({\n queryKey: [QK, 'dashboard'],\n queryFn: async () => {\n const data = await pswQuery<{ pswDashboardStats: PswDashboardStats }>(`\n query PswDashboard {\n pswDashboardStats {\n totalClients activeClients activeEngagements openMatters\n outstandingInvoiceTotal paidInvoiceTotal unbilledHours billedHours\n pendingComplianceChecks openConflictChecks\n engagementsByStatus { status count }\n invoicesByStatus { status count }\n mattersByStatus { status count }\n revenueByMonth { month amount }\n }\n }`);\n return data.pswDashboardStats;\n },\n });\n}\n\n// ============================================================================\n// Clients\n// ============================================================================\n\nexport function useClients(\n args: { status?: PswClientStatus; search?: string; pagination?: PswPagination } = {}\n) {\n return useQuery({\n queryKey: [QK, 'clients', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListClients: PswConnection<PswClient> }>(\n `query PswClients($status: PswClientStatus, $search: String, $pagination: PaginationInput) {\n pswListClients(status: $status, search: $search, pagination: $pagination) {\n items { ${CLIENT_F} } pageInfo { hasMore cursor } totalCount\n }\n }`,\n {\n status: args.status ?? null,\n search: args.search ?? null,\n pagination: args.pagination ?? { limit: 100 },\n }\n );\n return data.pswListClients;\n },\n });\n}\n\nexport function useClient(id: string | null) {\n return useQuery({\n queryKey: [QK, 'client', id],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await pswQuery<{ pswClient: PswClientDetail | null }>(\n `query PswClient($id: ID!) {\n pswClient(id: $id) {\n ${CLIENT_F}\n engagements { ${ENGAGEMENT_F} }\n matters { ${MATTER_F} }\n }\n }`,\n { id }\n );\n return data.pswClient;\n },\n });\n}\n\nexport function useCreateClient() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery<{ pswCreateClient: PswClient }>(\n `mutation PswCreateClient($input: PswCreateClientInput!) { pswCreateClient(input: $input) { ${CLIENT_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'clients', 'dashboard'),\n });\n}\nexport function useUpdateClient() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; input: Record<string, unknown> }) =>\n pswQuery(\n `mutation PswUpdateClient($id: ID!, $input: PswUpdateClientInput!) { pswUpdateClient(id: $id, input: $input) { ${CLIENT_F} } }`,\n vars\n ),\n onSuccess: (_d, v) => {\n invalidate(qc, 'clients', 'dashboard');\n void qc.invalidateQueries({ queryKey: [QK, 'client', v.id] });\n },\n });\n}\nexport function useArchiveClient() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n pswQuery(`mutation PswArchiveClient($id: ID!) { pswArchiveClient(id: $id) }`, { id }),\n onSuccess: () => invalidate(qc, 'clients', 'dashboard'),\n });\n}\n\n// ============================================================================\n// Engagements\n// ============================================================================\n\nexport function useEngagements(\n args: {\n clientId?: string;\n status?: PswEngagementStatus;\n search?: string;\n pagination?: PswPagination;\n } = {}\n) {\n return useQuery({\n queryKey: [QK, 'engagements', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListEngagements: PswConnection<PswEngagement> }>(\n `query PswEngagements($clientId: ID, $status: PswEngagementStatus, $search: String, $pagination: PaginationInput) {\n pswListEngagements(clientId: $clientId, status: $status, search: $search, pagination: $pagination) {\n items { ${ENGAGEMENT_F} } pageInfo { hasMore cursor } totalCount\n }\n }`,\n {\n clientId: args.clientId ?? null,\n status: args.status ?? null,\n search: args.search ?? null,\n pagination: args.pagination ?? { limit: 100 },\n }\n );\n return data.pswListEngagements;\n },\n });\n}\n\nexport function useEngagement(id: string | null) {\n return useQuery({\n queryKey: [QK, 'engagement', id],\n enabled: Boolean(id),\n queryFn: async () => {\n const data = await pswQuery<{ pswEngagement: PswEngagementDetail | null }>(\n `query PswEngagement($id: ID!) {\n pswEngagement(id: $id) {\n ${ENGAGEMENT_F}\n deliverables { ${DELIVERABLE_F} }\n milestones { ${MILESTONE_F} }\n }\n }`,\n { id }\n );\n return data.pswEngagement;\n },\n });\n}\n\nexport function useCreateEngagement() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateEngagement($input: PswCreateEngagementInput!) { pswCreateEngagement(input: $input) { ${ENGAGEMENT_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'engagements', 'dashboard'),\n });\n}\nexport function useUpdateEngagement() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; input: Record<string, unknown> }) =>\n pswQuery(\n `mutation PswUpdateEngagement($id: ID!, $input: PswUpdateEngagementInput!) { pswUpdateEngagement(id: $id, input: $input) { ${ENGAGEMENT_F} } }`,\n vars\n ),\n onSuccess: (_d, v) => {\n invalidate(qc, 'engagements');\n void qc.invalidateQueries({ queryKey: [QK, 'engagement', v.id] });\n },\n });\n}\nexport function useTransitionEngagement() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; status: PswEngagementStatus }) =>\n pswQuery(\n `mutation PswTransitionEngagement($id: ID!, $status: PswEngagementStatus!) { pswTransitionEngagement(id: $id, status: $status) { ${ENGAGEMENT_F} } }`,\n vars\n ),\n onSuccess: (_d, v) => {\n invalidate(qc, 'engagements', 'dashboard');\n void qc.invalidateQueries({ queryKey: [QK, 'engagement', v.id] });\n },\n });\n}\n\n// ============================================================================\n// Deliverables & Milestones (engagement delivery)\n// ============================================================================\n\nexport function useCreateDeliverable() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateDeliverable($input: PswCreateDeliverableInput!) { pswCreateDeliverable(input: $input) { ${DELIVERABLE_F} } }`,\n { input }\n ),\n onSuccess: (_d, input) =>\n qc.invalidateQueries({\n queryKey: [QK, 'engagement', (input as { engagementId: string }).engagementId],\n }),\n });\n}\nexport function useTransitionDeliverable() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; status: PswDeliverableStatus; engagementId: string }) =>\n pswQuery(\n `mutation PswTransitionDeliverable($id: ID!, $status: PswDeliverableStatus!) { pswTransitionDeliverable(id: $id, status: $status) { ${DELIVERABLE_F} } }`,\n {\n id: vars.id,\n status: vars.status,\n }\n ),\n onSuccess: (_d, v) => qc.invalidateQueries({ queryKey: [QK, 'engagement', v.engagementId] }),\n });\n}\nexport function useCreateMilestone() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateMilestone($input: PswCreateMilestoneInput!) { pswCreateMilestone(input: $input) { ${MILESTONE_F} } }`,\n { input }\n ),\n onSuccess: (_d, input) =>\n qc.invalidateQueries({\n queryKey: [QK, 'engagement', (input as { engagementId: string }).engagementId],\n }),\n });\n}\nexport function useCompleteMilestone() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; engagementId: string }) =>\n pswQuery(\n `mutation PswCompleteMilestone($id: ID!) { pswCompleteMilestone(id: $id) { ${MILESTONE_F} } }`,\n { id: vars.id }\n ),\n onSuccess: (_d, v) => qc.invalidateQueries({ queryKey: [QK, 'engagement', v.engagementId] }),\n });\n}\n\n// ============================================================================\n// Matters\n// ============================================================================\n\nexport function useMatters(\n args: {\n clientId?: string;\n engagementId?: string;\n status?: PswMatterStatus;\n search?: string;\n pagination?: PswPagination;\n } = {}\n) {\n return useQuery({\n queryKey: [QK, 'matters', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListMatters: PswConnection<PswMatter> }>(\n `query PswMatters($clientId: ID, $engagementId: ID, $status: PswMatterStatus, $search: String, $pagination: PaginationInput) {\n pswListMatters(clientId: $clientId, engagementId: $engagementId, status: $status, search: $search, pagination: $pagination) {\n items { ${MATTER_F} } pageInfo { hasMore cursor } totalCount\n }\n }`,\n {\n clientId: args.clientId ?? null,\n engagementId: args.engagementId ?? null,\n status: args.status ?? null,\n search: args.search ?? null,\n pagination: args.pagination ?? { limit: 100 },\n }\n );\n return data.pswListMatters;\n },\n });\n}\nexport function useCreateMatter() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateMatter($input: PswCreateMatterInput!) { pswCreateMatter(input: $input) { ${MATTER_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'matters', 'dashboard'),\n });\n}\nexport function useUpdateMatter() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; input: Record<string, unknown> }) =>\n pswQuery(\n `mutation PswUpdateMatter($id: ID!, $input: PswUpdateMatterInput!) { pswUpdateMatter(id: $id, input: $input) { ${MATTER_F} } }`,\n vars\n ),\n onSuccess: () => invalidate(qc, 'matters'),\n });\n}\nexport function useCloseMatter() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n pswQuery(`mutation PswCloseMatter($id: ID!) { pswCloseMatter(id: $id) { ${MATTER_F} } }`, {\n id,\n }),\n onSuccess: () => invalidate(qc, 'matters', 'dashboard'),\n });\n}\n\n// ============================================================================\n// Time entries\n// ============================================================================\n\nexport function useTimeEntries(\n args: {\n engagementId?: string;\n matterId?: string;\n status?: PswTimeEntryStatus;\n billable?: boolean;\n pagination?: PswPagination;\n } = {}\n) {\n return useQuery({\n queryKey: [QK, 'time', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListTimeEntries: PswConnection<PswTimeEntry> }>(\n `query PswTimeEntries($engagementId: ID, $matterId: ID, $status: PswTimeEntryStatus, $billable: Boolean, $pagination: PaginationInput) {\n pswListTimeEntries(engagementId: $engagementId, matterId: $matterId, status: $status, billable: $billable, pagination: $pagination) {\n items { ${TIME_F} } pageInfo { hasMore cursor } totalCount\n }\n }`,\n {\n engagementId: args.engagementId ?? null,\n matterId: args.matterId ?? null,\n status: args.status ?? null,\n billable: args.billable ?? null,\n pagination: args.pagination ?? { limit: 100 },\n }\n );\n return data.pswListTimeEntries;\n },\n });\n}\nexport function useLogTimeEntry() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswLogTime($input: PswCreateTimeEntryInput!) { pswLogTimeEntry(input: $input) { ${TIME_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'time', 'dashboard'),\n });\n}\nexport function useSubmitTimeEntry() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n pswQuery(`mutation PswSubmitTime($id: ID!) { pswSubmitTimeEntry(id: $id) { ${TIME_F} } }`, {\n id,\n }),\n onSuccess: () => invalidate(qc, 'time'),\n });\n}\nexport function useApproveTimeEntry() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n pswQuery(`mutation PswApproveTime($id: ID!) { pswApproveTimeEntry(id: $id) { ${TIME_F} } }`, {\n id,\n }),\n onSuccess: () => invalidate(qc, 'time'),\n });\n}\n\n// ============================================================================\n// Invoices\n// ============================================================================\n\nexport function useInvoices(\n args: { clientId?: string; status?: PswInvoiceStatus; pagination?: PswPagination } = {}\n) {\n return useQuery({\n queryKey: [QK, 'invoices', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListInvoices: PswConnection<PswInvoice> }>(\n `query PswInvoices($clientId: ID, $status: PswInvoiceStatus, $pagination: PaginationInput) {\n pswListInvoices(clientId: $clientId, status: $status, pagination: $pagination) {\n items { ${INVOICE_F} } pageInfo { hasMore cursor } totalCount\n }\n }`,\n {\n clientId: args.clientId ?? null,\n status: args.status ?? null,\n pagination: args.pagination ?? { limit: 100 },\n }\n );\n return data.pswListInvoices;\n },\n });\n}\nexport function useCreateInvoice() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateInvoice($input: PswCreateInvoiceInput!) { pswCreateInvoice(input: $input) { ${INVOICE_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'invoices', 'dashboard'),\n });\n}\nexport function useMarkInvoicePaid() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n pswQuery(`mutation PswMarkPaid($id: ID!) { pswMarkInvoicePaid(id: $id) { ${INVOICE_F} } }`, {\n id,\n }),\n onSuccess: () => invalidate(qc, 'invoices', 'dashboard'),\n });\n}\n\n// ============================================================================\n// Compliance\n// ============================================================================\n\nexport function useComplianceChecks(\n args: { status?: PswComplianceStatus; pagination?: PswPagination } = {}\n) {\n return useQuery({\n queryKey: [QK, 'compliance', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListComplianceChecks: PswComplianceCheck[] }>(\n `query PswCompliance($status: PswComplianceStatus, $pagination: PaginationInput) {\n pswListComplianceChecks(status: $status, pagination: $pagination) { ${COMPLIANCE_F} }\n }`,\n { status: args.status ?? null, pagination: args.pagination ?? { limit: 100 } }\n );\n return data.pswListComplianceChecks;\n },\n });\n}\nexport function useCreateComplianceCheck() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateCompliance($input: PswCreateComplianceCheckInput!) { pswCreateComplianceCheck(input: $input) { ${COMPLIANCE_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'compliance', 'dashboard'),\n });\n}\nexport function useResolveComplianceCheck() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; status: PswComplianceStatus; details?: string }) =>\n pswQuery(\n `mutation PswResolveCompliance($id: ID!, $status: PswComplianceStatus!, $details: String) { pswResolveComplianceCheck(id: $id, status: $status, details: $details) { ${COMPLIANCE_F} } }`,\n vars\n ),\n onSuccess: () => invalidate(qc, 'compliance', 'dashboard'),\n });\n}\n\n// ============================================================================\n// Conflict checks\n// ============================================================================\n\nexport function useConflictChecks(args: { clientId?: string; pagination?: PswPagination } = {}) {\n return useQuery({\n queryKey: [QK, 'conflicts', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListConflictChecks: PswConflictCheck[] }>(\n `query PswConflicts($clientId: ID, $pagination: PaginationInput) {\n pswListConflictChecks(clientId: $clientId, pagination: $pagination) { ${CONFLICT_F} }\n }`,\n { clientId: args.clientId ?? null, pagination: args.pagination ?? { limit: 100 } }\n );\n return data.pswListConflictChecks;\n },\n });\n}\nexport function useCreateConflictCheck() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateConflict($input: PswCreateConflictCheckInput!) { pswCreateConflictCheck(input: $input) { ${CONFLICT_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'conflicts', 'dashboard'),\n });\n}\nexport function useResolveConflictCheck() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: {\n id: string;\n status: PswConflictCheckStatus;\n findings?: string;\n waiverReason?: string;\n }) =>\n pswQuery(\n `mutation PswResolveConflict($id: ID!, $status: PswConflictCheckStatus!, $findings: String, $waiverReason: String) {\n pswResolveConflictCheck(id: $id, status: $status, findings: $findings, waiverReason: $waiverReason) { ${CONFLICT_F} }\n }`,\n vars\n ),\n onSuccess: () => invalidate(qc, 'conflicts', 'dashboard'),\n });\n}\n\n// ============================================================================\n// Practice areas\n// ============================================================================\n\nexport function usePracticeAreas() {\n return useQuery({\n queryKey: [QK, 'practiceAreas'],\n queryFn: async () => {\n const data = await pswQuery<{ pswListPracticeAreas: PswPracticeArea[] }>(\n `query PswPracticeAreas { pswListPracticeAreas(pagination: { limit: 100 }) { ${PRACTICE_AREA_F} } }`\n );\n return data.pswListPracticeAreas;\n },\n });\n}\nexport function useCreatePracticeArea() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreatePracticeArea($input: PswCreatePracticeAreaInput!) { pswCreatePracticeArea(input: $input) { ${PRACTICE_AREA_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'practiceAreas'),\n });\n}\nexport function useUpdatePracticeArea() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (vars: { id: string; input: Record<string, unknown> }) =>\n pswQuery(\n `mutation PswUpdatePracticeArea($id: ID!, $input: PswUpdatePracticeAreaInput!) { pswUpdatePracticeArea(id: $id, input: $input) { ${PRACTICE_AREA_F} } }`,\n vars\n ),\n onSuccess: () => invalidate(qc, 'practiceAreas'),\n });\n}\n\n// ============================================================================\n// Documents (metadata over wspace-files-svc)\n// ============================================================================\n\nexport function useDocuments(\n args: {\n engagementId?: string;\n matterId?: string;\n classification?: PswDocumentClassification;\n status?: PswDocumentStatus;\n pagination?: PswPagination;\n } = {}\n) {\n return useQuery({\n queryKey: [QK, 'documents', args],\n queryFn: async () => {\n const data = await pswQuery<{ pswListDocuments: PswConnection<PswDocument> }>(\n `query PswDocuments($engagementId: ID, $matterId: ID, $classification: PswDocumentClassification, $status: PswDocumentStatus, $pagination: PaginationInput) {\n pswListDocuments(engagementId: $engagementId, matterId: $matterId, classification: $classification, status: $status, pagination: $pagination) {\n items { ${DOCUMENT_F} } pageInfo { hasMore cursor } totalCount\n }\n }`,\n {\n engagementId: args.engagementId ?? null,\n matterId: args.matterId ?? null,\n classification: args.classification ?? null,\n status: args.status ?? null,\n pagination: args.pagination ?? { limit: 100 },\n }\n );\n return data.pswListDocuments;\n },\n });\n}\nexport function useCreateDocument() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (input: Record<string, unknown>) =>\n pswQuery(\n `mutation PswCreateDocument($input: PswCreateDocumentInput!) { pswCreateDocument(input: $input) { ${DOCUMENT_F} } }`,\n { input }\n ),\n onSuccess: () => invalidate(qc, 'documents'),\n });\n}\nexport function useArchiveDocument() {\n const qc = useQueryClient();\n return useMutation({\n mutationFn: (id: string) =>\n pswQuery(\n `mutation PswArchiveDocument($id: ID!) { pswArchiveDocument(id: $id) { ${DOCUMENT_F} } }`,\n { id }\n ),\n onSuccess: () => invalidate(qc, 'documents'),\n });\n}\n"],"mappings":"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"}
|