@fayz-ai/forms 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +34 -2
- package/dist/chunk-2KVTEW7I.js +211 -0
- package/dist/chunk-2KVTEW7I.js.map +1 -0
- package/dist/chunk-JO4REIZC.js +429 -0
- package/dist/chunk-JO4REIZC.js.map +1 -0
- package/dist/chunk-L2KPTYH4.js +11 -0
- package/dist/chunk-L2KPTYH4.js.map +1 -0
- package/dist/chunk-LQJONAVT.js +25 -0
- package/dist/chunk-LQJONAVT.js.map +1 -0
- package/dist/data/mock.d.ts +3 -0
- package/dist/data/mock.d.ts.map +1 -0
- package/dist/data/mock.js +4 -0
- package/dist/data/mock.js.map +1 -0
- package/dist/data/provider.d.ts +55 -0
- package/dist/data/provider.d.ts.map +1 -0
- package/dist/data/provider.js +3 -0
- package/dist/data/provider.js.map +1 -0
- package/dist/data/supabase.d.ts +6 -0
- package/dist/data/supabase.d.ts.map +1 -0
- package/dist/data/supabase.js +4 -0
- package/dist/data/supabase.js.map +1 -0
- package/dist/data/tables.d.ts +7 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/data/tables.js +3 -0
- package/dist/data/tables.js.map +1 -0
- package/dist/domain/document.d.ts +84 -0
- package/dist/domain/document.d.ts.map +1 -0
- package/dist/domain/document.js +3 -0
- package/dist/domain/document.js.map +1 -0
- package/dist/domain/requirement.d.ts +27 -0
- package/dist/domain/requirement.d.ts.map +1 -0
- package/dist/domain/requirement.js +3 -0
- package/dist/domain/requirement.js.map +1 -0
- package/dist/domain/template.d.ts +135 -0
- package/dist/domain/template.d.ts.map +1 -0
- package/dist/domain/template.js +3 -0
- package/dist/domain/template.js.map +1 -0
- package/dist/store.d.ts +37 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +138 -0
- package/dist/store.js.map +1 -0
- package/dist/views/zones.d.ts +75 -0
- package/dist/views/zones.d.ts.map +1 -0
- package/dist/views/zones.js +11 -0
- package/dist/views/zones.js.map +1 -0
- package/package.json +48 -3
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CreateDocumentInput, DocumentCounts, DocumentFile, DocumentQuery, FormDocument, PaginatedResult, UpdateDocumentInput } from '../domain/document';
|
|
2
|
+
import type { PersonFormRequirement } from '../domain/requirement';
|
|
3
|
+
import type { CreateTemplateInput, FormTemplate, TemplateQuery, TemplateUsage, UpdateTemplateInput } from '../domain/template';
|
|
4
|
+
export interface FormsDataProvider {
|
|
5
|
+
getTemplates(query: TemplateQuery): Promise<PaginatedResult<FormTemplate>>;
|
|
6
|
+
getTemplateById(id: string): Promise<FormTemplate | null>;
|
|
7
|
+
createTemplate(input: CreateTemplateInput): Promise<FormTemplate>;
|
|
8
|
+
updateTemplate(id: string, input: UpdateTemplateInput): Promise<FormTemplate>;
|
|
9
|
+
deleteTemplate(id: string): Promise<void>;
|
|
10
|
+
/** Keyed by template id; a template with no documents is absent. */
|
|
11
|
+
getTemplateUsage(): Promise<Record<string, TemplateUsage>>;
|
|
12
|
+
getDocuments(query: DocumentQuery): Promise<PaginatedResult<FormDocument>>;
|
|
13
|
+
/** Real totals per bucket; the document list is paginated, so counting a page undercounts. */
|
|
14
|
+
getDocumentCounts(query: {
|
|
15
|
+
personId: string;
|
|
16
|
+
kinds?: string[];
|
|
17
|
+
}): Promise<DocumentCounts>;
|
|
18
|
+
getDocumentById(id: string): Promise<FormDocument | null>;
|
|
19
|
+
createDocument(input: CreateDocumentInput): Promise<FormDocument>;
|
|
20
|
+
updateDocument(id: string, input: UpdateDocumentInput): Promise<FormDocument>;
|
|
21
|
+
deleteDocument(id: string): Promise<void>;
|
|
22
|
+
getDocumentFiles(documentId: string): Promise<DocumentFile[]>;
|
|
23
|
+
uploadFile(documentId: string, fieldKey: string, file: File): Promise<DocumentFile>;
|
|
24
|
+
deleteFile(fileId: string): Promise<void>;
|
|
25
|
+
/** The forms this person must have filled; empty when the house requires none. */
|
|
26
|
+
getPersonRequirements(personId: string): Promise<PersonFormRequirement[]>;
|
|
27
|
+
/** `folder` is relative to `<tenant>/forms/`. */
|
|
28
|
+
uploadMedia?(blob: Blob, folder: string, fileName: string): Promise<{
|
|
29
|
+
path: string;
|
|
30
|
+
}>;
|
|
31
|
+
/** Short-lived URL to show a stored path. */
|
|
32
|
+
mediaUrl?(path: string): Promise<string | null>;
|
|
33
|
+
searchCatalog?(term: string): Promise<CatalogOption[]>;
|
|
34
|
+
/** The latest answer of each template that has alert-raising fields, for one person. */
|
|
35
|
+
getLatestAnswers?(personId: string, templateIds: string[]): Promise<Array<{
|
|
36
|
+
templateId: string;
|
|
37
|
+
data: Record<string, unknown>;
|
|
38
|
+
at: string;
|
|
39
|
+
}>>;
|
|
40
|
+
getPackageServices?(packageId: string): Promise<Array<{
|
|
41
|
+
serviceId: string;
|
|
42
|
+
name: string;
|
|
43
|
+
unitPrice: number;
|
|
44
|
+
quantity: number;
|
|
45
|
+
}>>;
|
|
46
|
+
}
|
|
47
|
+
export interface CatalogOption {
|
|
48
|
+
kind: 'service' | 'package';
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
price: number;
|
|
52
|
+
/** Family the V1 picker groups by. */
|
|
53
|
+
group: string | null;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/data/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"provider.js"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PersonFormRequirement } from '../domain/requirement';
|
|
2
|
+
import type { FormsDataProvider } from './provider';
|
|
3
|
+
/** The forms this person must have filled in this tenant; empty when the house requires none. */
|
|
4
|
+
export declare function getPersonFormRequirements(tenantId: string, personId: string): Promise<PersonFormRequirement[]>;
|
|
5
|
+
export declare function createSupabaseFormsProvider(): FormsDataProvider;
|
|
6
|
+
//# sourceMappingURL=supabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,qBAAqB,EAAoB,MAAM,uBAAuB,CAAA;AAUpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAsNnD,iGAAiG;AACjG,wBAAsB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAOpH;AAED,wBAAgB,2BAA2B,IAAI,iBAAiB,CAmc/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"supabase.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/data/tables.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,CAAC;;;;;CAKJ,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"tables.js"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { TemplateCategory } from './template';
|
|
2
|
+
export type DocumentStatus = 'draft' | 'completed' | 'signed' | 'archived';
|
|
3
|
+
export interface FormDocument {
|
|
4
|
+
id: string;
|
|
5
|
+
tenantId: string;
|
|
6
|
+
templateId: string;
|
|
7
|
+
templateName?: string;
|
|
8
|
+
templateCategory?: TemplateCategory;
|
|
9
|
+
personId?: string;
|
|
10
|
+
personName?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
data: Record<string, unknown>;
|
|
13
|
+
status: DocumentStatus;
|
|
14
|
+
signedAt?: string;
|
|
15
|
+
signedBy?: string;
|
|
16
|
+
notes?: string;
|
|
17
|
+
metadata: Record<string, unknown>;
|
|
18
|
+
isDeleted: boolean;
|
|
19
|
+
createdBy?: string;
|
|
20
|
+
updatedBy?: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
/** `public.documents.kind`: `form`, `image`, `attachment`… */
|
|
24
|
+
kind?: string;
|
|
25
|
+
fileUrl?: string;
|
|
26
|
+
fileName?: string;
|
|
27
|
+
fileSize?: number;
|
|
28
|
+
mimeType?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface DocumentFile {
|
|
31
|
+
id: string;
|
|
32
|
+
tenantId: string;
|
|
33
|
+
documentId: string;
|
|
34
|
+
fieldKey: string;
|
|
35
|
+
fileUrl: string;
|
|
36
|
+
fileName?: string;
|
|
37
|
+
fileSize?: number;
|
|
38
|
+
mimeType?: string;
|
|
39
|
+
sortOrder: number;
|
|
40
|
+
metadata: Record<string, unknown>;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
}
|
|
43
|
+
export interface DocumentQuery {
|
|
44
|
+
personId?: string;
|
|
45
|
+
templateId?: string;
|
|
46
|
+
status?: DocumentStatus | DocumentStatus[];
|
|
47
|
+
search?: string;
|
|
48
|
+
page?: number;
|
|
49
|
+
pageSize?: number;
|
|
50
|
+
/** Filtered on the server: a page of 50 rows filtered afterwards can hide every photo. */
|
|
51
|
+
kinds?: string[];
|
|
52
|
+
templateCategory?: string;
|
|
53
|
+
}
|
|
54
|
+
/** Documents per record bucket: the template category, or `file` for photos and attachments. */
|
|
55
|
+
export type DocumentCounts = Record<string, number>;
|
|
56
|
+
export interface PaginatedResult<T> {
|
|
57
|
+
data: T[];
|
|
58
|
+
total: number;
|
|
59
|
+
}
|
|
60
|
+
export interface CreateDocumentInput {
|
|
61
|
+
templateId?: string;
|
|
62
|
+
personId?: string;
|
|
63
|
+
title?: string;
|
|
64
|
+
data?: Record<string, unknown>;
|
|
65
|
+
status?: DocumentStatus;
|
|
66
|
+
kind?: string;
|
|
67
|
+
fileUrl?: string;
|
|
68
|
+
fileName?: string;
|
|
69
|
+
fileSize?: number;
|
|
70
|
+
mimeType?: string;
|
|
71
|
+
/** What the answer hangs on — the attendance ruler resolves a form by `appointment` + id. */
|
|
72
|
+
subjectType?: string;
|
|
73
|
+
subjectId?: string;
|
|
74
|
+
/** The service the answer refers to (service-scoped forms). */
|
|
75
|
+
productId?: string;
|
|
76
|
+
professionalId?: string;
|
|
77
|
+
}
|
|
78
|
+
export interface UpdateDocumentInput {
|
|
79
|
+
data?: Record<string, unknown>;
|
|
80
|
+
status?: DocumentStatus;
|
|
81
|
+
title?: string;
|
|
82
|
+
notes?: string;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=document.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/domain/document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAA;AAE1E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,MAAM,EAAE,cAAc,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,cAAc,GAAG,cAAc,EAAE,CAAA;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0FAA0F;IAC1F,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,gGAAgG;AAChG,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEnD,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"document.js"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { FormDocument } from './document';
|
|
2
|
+
import type { FormTemplate } from './template';
|
|
3
|
+
/** Decided by the database (`forms_person_requirements`), so every screen agrees on validity. */
|
|
4
|
+
export type RequirementState = 'pending' | 'expired' | 'valid';
|
|
5
|
+
export interface PersonFormRequirement {
|
|
6
|
+
templateId: string;
|
|
7
|
+
templateName: string;
|
|
8
|
+
category: string;
|
|
9
|
+
validityDays: number | null;
|
|
10
|
+
/** The template asks for a missing answer to be shown up front, not only in the checklist. */
|
|
11
|
+
alertWhenMissing: boolean;
|
|
12
|
+
/** `null` when never filled. */
|
|
13
|
+
lastFilledAt: string | null;
|
|
14
|
+
/** `null` when it never expires or was never filled. */
|
|
15
|
+
validUntil: string | null;
|
|
16
|
+
state: RequirementState;
|
|
17
|
+
}
|
|
18
|
+
/** Never filled or expired. */
|
|
19
|
+
export declare const isOutstanding: (r: PersonFormRequirement) => boolean;
|
|
20
|
+
/** What the person checklist shows: everything up to date, and only the gaps that ask to alert. */
|
|
21
|
+
export declare const shownInChecklist: (r: PersonFormRequirement) => boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The same answer `forms_person_requirements` gives in SQL: every active template required on
|
|
24
|
+
* attendance, with the person's latest answer (signed, else created) and whether it still holds on `today`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function personRequirements(templates: readonly FormTemplate[], documents: readonly FormDocument[], personId: string, today: string): PersonFormRequirement[];
|
|
27
|
+
//# sourceMappingURL=requirement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirement.d.ts","sourceRoot":"","sources":["../../src/domain/requirement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,iGAAiG;AACjG,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;AAE9D,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,8FAA8F;IAC9F,gBAAgB,EAAE,OAAO,CAAA;IACzB,gCAAgC;IAChC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,wDAAwD;IACxD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,EAAE,gBAAgB,CAAA;CACxB;AAED,+BAA+B;AAC/B,eAAO,MAAM,aAAa,GAAI,GAAG,qBAAqB,KAAG,OAA8B,CAAA;AAEvF,mGAAmG;AACnG,eAAO,MAAM,gBAAgB,GAAI,GAAG,qBAAqB,KAAG,OAAkD,CAAA;AAI9G;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,qBAAqB,EAAE,CA0BzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"requirement.js"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
export type FormFieldType = 'title' | 'text' | 'memo' | 'richtext' | 'date' | 'select' | 'radio' | 'tags' | 'checkbox' | 'image' | 'gallery' | 'budget' | 'yes_no' | 'yes_no_text' | 'stencil_photo' | 'recommendation' | 'signature';
|
|
2
|
+
export interface FormFieldDef {
|
|
3
|
+
id: string;
|
|
4
|
+
type: FormFieldType;
|
|
5
|
+
label: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
/** 0-based start column on the 12-column grid. */
|
|
9
|
+
col: number;
|
|
10
|
+
row: number;
|
|
11
|
+
/** 1 to 12. */
|
|
12
|
+
colSpan: number;
|
|
13
|
+
rowSpan?: number;
|
|
14
|
+
/** For select, radio and tags. */
|
|
15
|
+
options?: Array<{
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** A person-record field that pre-fills this one on a new document, e.g. `documentNumber`. */
|
|
20
|
+
map?: string;
|
|
21
|
+
/** Applied to a new document when no mapped value exists, e.g. a contract clause. */
|
|
22
|
+
defaultValue?: unknown;
|
|
23
|
+
/** Type-specific configuration — see the `*Config` shapes below. */
|
|
24
|
+
config?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
/** `stencil_photo` → `config.stencil`. */
|
|
27
|
+
export interface StencilConfig {
|
|
28
|
+
/** Storage path (attachments bucket) of the overlay PNG. */
|
|
29
|
+
overlayPath?: string;
|
|
30
|
+
opacity?: number;
|
|
31
|
+
aspect?: '3:4' | '1:1' | '4:3';
|
|
32
|
+
camera?: 'user' | 'environment';
|
|
33
|
+
/** Draw the overlay into the saved photo. */
|
|
34
|
+
burnOverlay?: boolean;
|
|
35
|
+
description?: string;
|
|
36
|
+
}
|
|
37
|
+
/** `gallery` → `config.gallery`. */
|
|
38
|
+
export interface GalleryConfig {
|
|
39
|
+
allowPhoto?: boolean;
|
|
40
|
+
allowVideo?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** `yes_no` / `yes_no_text` → `config.alert`: the answer that raises a clinical alert. */
|
|
43
|
+
export interface AnswerAlertConfig {
|
|
44
|
+
trigger?: 'sim' | 'nao' | 'never';
|
|
45
|
+
severity?: 'danger' | 'warning' | 'info';
|
|
46
|
+
message?: string;
|
|
47
|
+
}
|
|
48
|
+
/** A photo, video or signature kept in storage; the value holds the path, never the bytes. */
|
|
49
|
+
export interface MediaValue {
|
|
50
|
+
path: string;
|
|
51
|
+
type: 'photo' | 'video' | 'signature';
|
|
52
|
+
name?: string;
|
|
53
|
+
}
|
|
54
|
+
/** `yes_no_text` value. `yes_no` stores just the answer. */
|
|
55
|
+
export interface YesNoTextValue {
|
|
56
|
+
answer: 'sim' | 'nao' | '';
|
|
57
|
+
text?: string;
|
|
58
|
+
}
|
|
59
|
+
/** One `recommendation` line. */
|
|
60
|
+
export interface RecommendationLine {
|
|
61
|
+
serviceId: string;
|
|
62
|
+
name: string;
|
|
63
|
+
unitPrice: number;
|
|
64
|
+
quantity: number;
|
|
65
|
+
/** Set when the line came from a package: the package is indicated through its services. */
|
|
66
|
+
packageId?: string;
|
|
67
|
+
packageName?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface FormSchema {
|
|
70
|
+
fields: FormFieldDef[];
|
|
71
|
+
layout: {
|
|
72
|
+
columns: 12;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export type TemplateCategory = 'anamnesis' | 'evolution' | 'report' | 'contract' | 'evaluation' | 'photos' | 'general';
|
|
76
|
+
export interface FormTemplate {
|
|
77
|
+
id: string;
|
|
78
|
+
tenantId: string;
|
|
79
|
+
name: string;
|
|
80
|
+
description?: string;
|
|
81
|
+
category: TemplateCategory;
|
|
82
|
+
version: number;
|
|
83
|
+
isCurrent: boolean;
|
|
84
|
+
parentId?: string;
|
|
85
|
+
schema: FormSchema;
|
|
86
|
+
specialty?: string;
|
|
87
|
+
tags: string[];
|
|
88
|
+
metadata: Record<string, unknown>;
|
|
89
|
+
isActive: boolean;
|
|
90
|
+
isDeleted: boolean;
|
|
91
|
+
/** Asked of every client before any attendance. */
|
|
92
|
+
requiredOnAttendance: boolean;
|
|
93
|
+
/** How many days an answer stays valid; `null` never expires. */
|
|
94
|
+
validityDays: number | null;
|
|
95
|
+
/** A missing answer is shown up front, not only in the attendance checklist. Off by default. */
|
|
96
|
+
alertWhenMissing: boolean;
|
|
97
|
+
createdBy?: string;
|
|
98
|
+
updatedBy?: string;
|
|
99
|
+
createdAt: string;
|
|
100
|
+
updatedAt: string;
|
|
101
|
+
}
|
|
102
|
+
export interface TemplateQuery {
|
|
103
|
+
category?: TemplateCategory;
|
|
104
|
+
search?: string;
|
|
105
|
+
page?: number;
|
|
106
|
+
pageSize?: number;
|
|
107
|
+
}
|
|
108
|
+
/** How much a template has been used; kept off `FormTemplate` so reading a template never pays for the aggregate. */
|
|
109
|
+
export interface TemplateUsage {
|
|
110
|
+
documentCount: number;
|
|
111
|
+
lastDocumentAt: string | null;
|
|
112
|
+
}
|
|
113
|
+
export interface CreateTemplateInput {
|
|
114
|
+
name: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
category: TemplateCategory;
|
|
117
|
+
schema: FormSchema;
|
|
118
|
+
specialty?: string;
|
|
119
|
+
tags?: string[];
|
|
120
|
+
metadata?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
export interface UpdateTemplateInput {
|
|
123
|
+
name?: string;
|
|
124
|
+
description?: string;
|
|
125
|
+
category?: TemplateCategory;
|
|
126
|
+
schema?: FormSchema;
|
|
127
|
+
specialty?: string;
|
|
128
|
+
tags?: string[];
|
|
129
|
+
metadata?: Record<string, unknown>;
|
|
130
|
+
isActive?: boolean;
|
|
131
|
+
requiredOnAttendance?: boolean;
|
|
132
|
+
validityDays?: number | null;
|
|
133
|
+
alertWhenMissing?: boolean;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/domain/template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"template.js"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { CreateDocumentInput, DocumentQuery, FormDocument, UpdateDocumentInput } from './domain/document';
|
|
2
|
+
import type { CreateTemplateInput, FormTemplate, TemplateQuery, TemplateUsage, UpdateTemplateInput } from './domain/template';
|
|
3
|
+
import type { FormsDataProvider } from './data/provider';
|
|
4
|
+
/** Supabase when a client is initialized, else the in-memory mock, resolved on first use. */
|
|
5
|
+
export declare function createSafeFormsProvider(): FormsDataProvider;
|
|
6
|
+
/** Prefix of `forms.template.created|updated|deleted`, emitted on the domain event bus so open lists re-read. */
|
|
7
|
+
export declare const FORM_TEMPLATE_EVENT = "forms.template.";
|
|
8
|
+
export interface FormsState {
|
|
9
|
+
templates: FormTemplate[];
|
|
10
|
+
templatesTotal: number;
|
|
11
|
+
templatesLoading: boolean;
|
|
12
|
+
templatesError: string | null;
|
|
13
|
+
/** Empty until `fetchTemplateUsage` answers, and when the pool can count neither way. */
|
|
14
|
+
templateUsage: Record<string, TemplateUsage>;
|
|
15
|
+
documents: FormDocument[];
|
|
16
|
+
documentsTotal: number;
|
|
17
|
+
documentsLoading: boolean;
|
|
18
|
+
documentsError: string | null;
|
|
19
|
+
activeTemplate: FormTemplate | null;
|
|
20
|
+
activeTemplateLoading: boolean;
|
|
21
|
+
activeDocument: FormDocument | null;
|
|
22
|
+
activeDocumentLoading: boolean;
|
|
23
|
+
fetchTemplates(query?: TemplateQuery): Promise<void>;
|
|
24
|
+
fetchTemplateUsage(): Promise<void>;
|
|
25
|
+
fetchTemplateById(id: string): Promise<FormTemplate | null>;
|
|
26
|
+
createTemplate(input: CreateTemplateInput): Promise<FormTemplate>;
|
|
27
|
+
updateTemplate(id: string, input: UpdateTemplateInput): Promise<FormTemplate>;
|
|
28
|
+
deleteTemplate(id: string): Promise<void>;
|
|
29
|
+
fetchDocuments(query?: DocumentQuery): Promise<void>;
|
|
30
|
+
fetchDocumentById(id: string): Promise<FormDocument | null>;
|
|
31
|
+
createDocument(input: CreateDocumentInput): Promise<FormDocument>;
|
|
32
|
+
updateDocument(id: string, input: UpdateDocumentInput): Promise<FormDocument>;
|
|
33
|
+
deleteDocument(id: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export declare function createFormsStore(provider: FormsDataProvider): import("zustand").UseBoundStore<import("zustand").StoreApi<FormsState>>;
|
|
36
|
+
export type FormsStore = ReturnType<typeof createFormsStore>;
|
|
37
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC9G,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAGxD,6FAA6F;AAC7F,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D;AAED,iHAAiH;AACjH,eAAO,MAAM,mBAAmB,oBAAoB,CAAA;AAUpD,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,YAAY,EAAE,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,OAAO,CAAA;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,yFAAyF;IACzF,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAE5C,SAAS,EAAE,YAAY,EAAE,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,OAAO,CAAA;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAE7B,cAAc,EAAE,YAAY,GAAG,IAAI,CAAA;IACnC,qBAAqB,EAAE,OAAO,CAAA;IAE9B,cAAc,EAAE,YAAY,GAAG,IAAI,CAAA;IACnC,qBAAqB,EAAE,OAAO,CAAA;IAE9B,cAAc,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC3D,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEzC,cAAc,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC3D,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,iBAAiB,2EAkI3D;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA"}
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { createMockFormsProvider } from './chunk-2KVTEW7I.js';
|
|
2
|
+
import { createSupabaseFormsProvider } from './chunk-JO4REIZC.js';
|
|
3
|
+
import './chunk-L2KPTYH4.js';
|
|
4
|
+
import './chunk-LQJONAVT.js';
|
|
5
|
+
import { create } from 'zustand';
|
|
6
|
+
import { createSafeDataProvider, emitDomainEvent, getActiveTenantId } from '@fayz-ai/core';
|
|
7
|
+
|
|
8
|
+
function createSafeFormsProvider() {
|
|
9
|
+
return createSafeDataProvider(createSupabaseFormsProvider, createMockFormsProvider);
|
|
10
|
+
}
|
|
11
|
+
var FORM_TEMPLATE_EVENT = "forms.template.";
|
|
12
|
+
function emitTemplateEvent(action, id, name) {
|
|
13
|
+
emitDomainEvent(
|
|
14
|
+
`${FORM_TEMPLATE_EVENT}${action}`,
|
|
15
|
+
{ record_id: id, record_name: name ?? null },
|
|
16
|
+
{ tenantId: getActiveTenantId() ?? null, subject: { type: "form_template", id } }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
function createFormsStore(provider) {
|
|
20
|
+
return create((set) => ({
|
|
21
|
+
templates: [],
|
|
22
|
+
templatesTotal: 0,
|
|
23
|
+
templatesLoading: false,
|
|
24
|
+
templatesError: null,
|
|
25
|
+
templateUsage: {},
|
|
26
|
+
documents: [],
|
|
27
|
+
documentsTotal: 0,
|
|
28
|
+
documentsLoading: false,
|
|
29
|
+
documentsError: null,
|
|
30
|
+
activeTemplate: null,
|
|
31
|
+
activeTemplateLoading: false,
|
|
32
|
+
activeDocument: null,
|
|
33
|
+
activeDocumentLoading: false,
|
|
34
|
+
async fetchTemplates(query) {
|
|
35
|
+
set({ templatesLoading: true, templatesError: null });
|
|
36
|
+
try {
|
|
37
|
+
const result = await provider.getTemplates(query ?? {});
|
|
38
|
+
set({ templates: result.data, templatesTotal: result.total });
|
|
39
|
+
} catch (e) {
|
|
40
|
+
set({ templatesError: e instanceof Error ? e.message : "Failed to fetch templates" });
|
|
41
|
+
} finally {
|
|
42
|
+
set({ templatesLoading: false });
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
// A failed count must not take the template list down with it.
|
|
46
|
+
async fetchTemplateUsage() {
|
|
47
|
+
try {
|
|
48
|
+
set({ templateUsage: await provider.getTemplateUsage() });
|
|
49
|
+
} catch {
|
|
50
|
+
set({ templateUsage: {} });
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
async fetchTemplateById(id) {
|
|
54
|
+
set({ activeTemplateLoading: true });
|
|
55
|
+
try {
|
|
56
|
+
const template = await provider.getTemplateById(id);
|
|
57
|
+
set({ activeTemplate: template });
|
|
58
|
+
return template;
|
|
59
|
+
} catch {
|
|
60
|
+
set({ activeTemplate: null });
|
|
61
|
+
return null;
|
|
62
|
+
} finally {
|
|
63
|
+
set({ activeTemplateLoading: false });
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
async createTemplate(input) {
|
|
67
|
+
const template = await provider.createTemplate(input);
|
|
68
|
+
set((s) => ({ templates: [template, ...s.templates], templatesTotal: s.templatesTotal + 1 }));
|
|
69
|
+
emitTemplateEvent("created", template.id, template.name);
|
|
70
|
+
return template;
|
|
71
|
+
},
|
|
72
|
+
async updateTemplate(id, input) {
|
|
73
|
+
const template = await provider.updateTemplate(id, input);
|
|
74
|
+
set((s) => ({
|
|
75
|
+
templates: s.templates.map((t) => t.id === id ? template : t),
|
|
76
|
+
activeTemplate: s.activeTemplate?.id === id ? template : s.activeTemplate
|
|
77
|
+
}));
|
|
78
|
+
emitTemplateEvent("updated", template.id, template.name);
|
|
79
|
+
return template;
|
|
80
|
+
},
|
|
81
|
+
async deleteTemplate(id) {
|
|
82
|
+
await provider.deleteTemplate(id);
|
|
83
|
+
emitTemplateEvent("deleted", id);
|
|
84
|
+
set((s) => ({
|
|
85
|
+
templates: s.templates.filter((t) => t.id !== id),
|
|
86
|
+
templatesTotal: s.templatesTotal - 1
|
|
87
|
+
}));
|
|
88
|
+
},
|
|
89
|
+
async fetchDocuments(query) {
|
|
90
|
+
set({ documentsLoading: true, documentsError: null });
|
|
91
|
+
try {
|
|
92
|
+
const result = await provider.getDocuments(query ?? {});
|
|
93
|
+
set({ documents: result.data, documentsTotal: result.total });
|
|
94
|
+
} catch (e) {
|
|
95
|
+
set({ documentsError: e instanceof Error ? e.message : "Failed to fetch documents" });
|
|
96
|
+
} finally {
|
|
97
|
+
set({ documentsLoading: false });
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
async fetchDocumentById(id) {
|
|
101
|
+
set({ activeDocumentLoading: true });
|
|
102
|
+
try {
|
|
103
|
+
const doc = await provider.getDocumentById(id);
|
|
104
|
+
set({ activeDocument: doc });
|
|
105
|
+
return doc;
|
|
106
|
+
} catch {
|
|
107
|
+
set({ activeDocument: null });
|
|
108
|
+
return null;
|
|
109
|
+
} finally {
|
|
110
|
+
set({ activeDocumentLoading: false });
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
async createDocument(input) {
|
|
114
|
+
const doc = await provider.createDocument(input);
|
|
115
|
+
set((s) => ({ documents: [doc, ...s.documents], documentsTotal: s.documentsTotal + 1 }));
|
|
116
|
+
return doc;
|
|
117
|
+
},
|
|
118
|
+
async updateDocument(id, input) {
|
|
119
|
+
const doc = await provider.updateDocument(id, input);
|
|
120
|
+
set((s) => ({
|
|
121
|
+
documents: s.documents.map((d) => d.id === id ? doc : d),
|
|
122
|
+
activeDocument: s.activeDocument?.id === id ? doc : s.activeDocument
|
|
123
|
+
}));
|
|
124
|
+
return doc;
|
|
125
|
+
},
|
|
126
|
+
async deleteDocument(id) {
|
|
127
|
+
await provider.deleteDocument(id);
|
|
128
|
+
set((s) => ({
|
|
129
|
+
documents: s.documents.filter((d) => d.id !== id),
|
|
130
|
+
documentsTotal: s.documentsTotal - 1
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { FORM_TEMPLATE_EVENT, createFormsStore, createSafeFormsProvider };
|
|
137
|
+
//# sourceMappingURL=store.js.map
|
|
138
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"store.js","sourcesContent":["import { create } from 'zustand'\nimport { createSafeDataProvider, emitDomainEvent, getActiveTenantId } from '@fayz-ai/core'\nimport type { CreateDocumentInput, DocumentQuery, FormDocument, UpdateDocumentInput } from './domain/document'\nimport type {\n CreateTemplateInput,\n FormTemplate,\n TemplateQuery,\n TemplateUsage,\n UpdateTemplateInput,\n} from './domain/template'\nimport { createMockFormsProvider } from './data/mock'\nimport type { FormsDataProvider } from './data/provider'\nimport { createSupabaseFormsProvider } from './data/supabase'\n\n/** Supabase when a client is initialized, else the in-memory mock, resolved on first use. */\nexport function createSafeFormsProvider(): FormsDataProvider {\n return createSafeDataProvider(createSupabaseFormsProvider, createMockFormsProvider)\n}\n\n/** Prefix of `forms.template.created|updated|deleted`, emitted on the domain event bus so open lists re-read. */\nexport const FORM_TEMPLATE_EVENT = 'forms.template.'\n\nfunction emitTemplateEvent(action: 'created' | 'updated' | 'deleted', id: string, name?: string): void {\n emitDomainEvent(\n `${FORM_TEMPLATE_EVENT}${action}`,\n { record_id: id, record_name: name ?? null },\n { tenantId: getActiveTenantId() ?? null, subject: { type: 'form_template', id } },\n )\n}\n\nexport interface FormsState {\n templates: FormTemplate[]\n templatesTotal: number\n templatesLoading: boolean\n templatesError: string | null\n /** Empty until `fetchTemplateUsage` answers, and when the pool can count neither way. */\n templateUsage: Record<string, TemplateUsage>\n\n documents: FormDocument[]\n documentsTotal: number\n documentsLoading: boolean\n documentsError: string | null\n\n activeTemplate: FormTemplate | null\n activeTemplateLoading: boolean\n\n activeDocument: FormDocument | null\n activeDocumentLoading: boolean\n\n fetchTemplates(query?: TemplateQuery): Promise<void>\n fetchTemplateUsage(): Promise<void>\n fetchTemplateById(id: string): Promise<FormTemplate | null>\n createTemplate(input: CreateTemplateInput): Promise<FormTemplate>\n updateTemplate(id: string, input: UpdateTemplateInput): Promise<FormTemplate>\n deleteTemplate(id: string): Promise<void>\n\n fetchDocuments(query?: DocumentQuery): Promise<void>\n fetchDocumentById(id: string): Promise<FormDocument | null>\n createDocument(input: CreateDocumentInput): Promise<FormDocument>\n updateDocument(id: string, input: UpdateDocumentInput): Promise<FormDocument>\n deleteDocument(id: string): Promise<void>\n}\n\nexport function createFormsStore(provider: FormsDataProvider) {\n return create<FormsState>((set) => ({\n templates: [],\n templatesTotal: 0,\n templatesLoading: false,\n templatesError: null,\n templateUsage: {},\n\n documents: [],\n documentsTotal: 0,\n documentsLoading: false,\n documentsError: null,\n\n activeTemplate: null,\n activeTemplateLoading: false,\n\n activeDocument: null,\n activeDocumentLoading: false,\n\n async fetchTemplates(query?: TemplateQuery) {\n set({ templatesLoading: true, templatesError: null })\n try {\n const result = await provider.getTemplates(query ?? {})\n set({ templates: result.data, templatesTotal: result.total })\n } catch (e) {\n set({ templatesError: e instanceof Error ? e.message : 'Failed to fetch templates' })\n } finally {\n set({ templatesLoading: false })\n }\n },\n\n // A failed count must not take the template list down with it.\n async fetchTemplateUsage() {\n try {\n set({ templateUsage: await provider.getTemplateUsage() })\n } catch {\n set({ templateUsage: {} })\n }\n },\n\n async fetchTemplateById(id: string) {\n set({ activeTemplateLoading: true })\n try {\n const template = await provider.getTemplateById(id)\n set({ activeTemplate: template })\n return template\n } catch {\n set({ activeTemplate: null })\n return null\n } finally {\n set({ activeTemplateLoading: false })\n }\n },\n\n async createTemplate(input: CreateTemplateInput) {\n const template = await provider.createTemplate(input)\n set((s) => ({ templates: [template, ...s.templates], templatesTotal: s.templatesTotal + 1 }))\n // Emitted on the write, not the screen: templates the assistant creates bypass this store.\n emitTemplateEvent('created', template.id, template.name)\n return template\n },\n\n async updateTemplate(id: string, input: UpdateTemplateInput) {\n const template = await provider.updateTemplate(id, input)\n set((s) => ({\n templates: s.templates.map((t) => (t.id === id ? template : t)),\n activeTemplate: s.activeTemplate?.id === id ? template : s.activeTemplate,\n }))\n emitTemplateEvent('updated', template.id, template.name)\n return template\n },\n\n async deleteTemplate(id: string) {\n await provider.deleteTemplate(id)\n emitTemplateEvent('deleted', id)\n set((s) => ({\n templates: s.templates.filter((t) => t.id !== id),\n templatesTotal: s.templatesTotal - 1,\n }))\n },\n\n async fetchDocuments(query?: DocumentQuery) {\n set({ documentsLoading: true, documentsError: null })\n try {\n const result = await provider.getDocuments(query ?? {})\n set({ documents: result.data, documentsTotal: result.total })\n } catch (e) {\n set({ documentsError: e instanceof Error ? e.message : 'Failed to fetch documents' })\n } finally {\n set({ documentsLoading: false })\n }\n },\n\n async fetchDocumentById(id: string) {\n set({ activeDocumentLoading: true })\n try {\n const doc = await provider.getDocumentById(id)\n set({ activeDocument: doc })\n return doc\n } catch {\n set({ activeDocument: null })\n return null\n } finally {\n set({ activeDocumentLoading: false })\n }\n },\n\n async createDocument(input: CreateDocumentInput) {\n const doc = await provider.createDocument(input)\n set((s) => ({ documents: [doc, ...s.documents], documentsTotal: s.documentsTotal + 1 }))\n return doc\n },\n\n async updateDocument(id: string, input: UpdateDocumentInput) {\n const doc = await provider.updateDocument(id, input)\n set((s) => ({\n documents: s.documents.map((d) => (d.id === id ? doc : d)),\n activeDocument: s.activeDocument?.id === id ? doc : s.activeDocument,\n }))\n return doc\n },\n\n async deleteDocument(id: string) {\n await provider.deleteDocument(id)\n set((s) => ({\n documents: s.documents.filter((d) => d.id !== id),\n documentsTotal: s.documentsTotal - 1,\n }))\n },\n }))\n}\n\nexport type FormsStore = ReturnType<typeof createFormsStore>\n"]}
|