evo360-types 1.3.394 → 1.3.395

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.
@@ -0,0 +1,282 @@
1
+ import { z } from "zod";
2
+ export declare const zQuickReplyActionStatusSchema: z.ZodEnum<["pending", "executed", "expired", "cancelled", "failed"]>;
3
+ export type IQuickReplyActionStatus = z.infer<typeof zQuickReplyActionStatusSchema>;
4
+ export declare const zQuickReplyActionRecipientSchema: z.ZodObject<{
5
+ contact_id: z.ZodOptional<z.ZodString>;
6
+ lead_id: z.ZodOptional<z.ZodString>;
7
+ patient_id: z.ZodOptional<z.ZodString>;
8
+ address: z.ZodString;
9
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
10
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
11
+ contact_id: z.ZodOptional<z.ZodString>;
12
+ lead_id: z.ZodOptional<z.ZodString>;
13
+ patient_id: z.ZodOptional<z.ZodString>;
14
+ address: z.ZodString;
15
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
16
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
17
+ contact_id: z.ZodOptional<z.ZodString>;
18
+ lead_id: z.ZodOptional<z.ZodString>;
19
+ patient_id: z.ZodOptional<z.ZodString>;
20
+ address: z.ZodString;
21
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
22
+ }, z.ZodTypeAny, "passthrough">>;
23
+ export declare const zQuickReplyActionResultSchema: z.ZodObject<{
24
+ success: z.ZodBoolean;
25
+ message: z.ZodOptional<z.ZodString>;
26
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
27
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
28
+ success: z.ZodBoolean;
29
+ message: z.ZodOptional<z.ZodString>;
30
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
31
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
32
+ success: z.ZodBoolean;
33
+ message: z.ZodOptional<z.ZodString>;
34
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
35
+ }, z.ZodTypeAny, "passthrough">>;
36
+ export declare const zQuickReplyActionCreatedBySchema: z.ZodObject<{
37
+ type: z.ZodEnum<["system", "human"]>;
38
+ user_id: z.ZodOptional<z.ZodString>;
39
+ module: z.ZodOptional<z.ZodString>;
40
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
41
+ type: z.ZodEnum<["system", "human"]>;
42
+ user_id: z.ZodOptional<z.ZodString>;
43
+ module: z.ZodOptional<z.ZodString>;
44
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
45
+ type: z.ZodEnum<["system", "human"]>;
46
+ user_id: z.ZodOptional<z.ZodString>;
47
+ module: z.ZodOptional<z.ZodString>;
48
+ }, z.ZodTypeAny, "passthrough">>;
49
+ export declare const zQuickReplyActionSchema: z.ZodObject<{
50
+ id: z.ZodString;
51
+ ref: z.ZodAny;
52
+ tenant: z.ZodString;
53
+ model_ver: z.ZodDefault<z.ZodNumber>;
54
+ created_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
55
+ updated_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
56
+ deleted_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
57
+ } & {
58
+ /** Action to execute (e.g. confirm_appointment, cancel_appointment...) */
59
+ action_type: z.ZodString;
60
+ /** Full action data the executor needs (never leaves the backend) */
61
+ action_payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
62
+ recipient: z.ZodObject<{
63
+ contact_id: z.ZodOptional<z.ZodString>;
64
+ lead_id: z.ZodOptional<z.ZodString>;
65
+ patient_id: z.ZodOptional<z.ZodString>;
66
+ address: z.ZodString;
67
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
68
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
69
+ contact_id: z.ZodOptional<z.ZodString>;
70
+ lead_id: z.ZodOptional<z.ZodString>;
71
+ patient_id: z.ZodOptional<z.ZodString>;
72
+ address: z.ZodString;
73
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
74
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
75
+ contact_id: z.ZodOptional<z.ZodString>;
76
+ lead_id: z.ZodOptional<z.ZodString>;
77
+ patient_id: z.ZodOptional<z.ZodString>;
78
+ address: z.ZodString;
79
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
80
+ }, z.ZodTypeAny, "passthrough">>;
81
+ /** Link to the notification message that delivered this action */
82
+ notification_message_id: z.ZodOptional<z.ZodString>;
83
+ template_name: z.ZodOptional<z.ZodString>;
84
+ button_index: z.ZodOptional<z.ZodNumber>;
85
+ button_label: z.ZodOptional<z.ZodString>;
86
+ /** Link to evo-chat thread/ticket (for timeline events) */
87
+ thread_id: z.ZodOptional<z.ZodString>;
88
+ ticket_id: z.ZodOptional<z.ZodString>;
89
+ status: z.ZodEnum<["pending", "executed", "expired", "cancelled", "failed"]>;
90
+ executed_at: z.ZodOptional<z.ZodDate>;
91
+ executed_by: z.ZodOptional<z.ZodString>;
92
+ executed_result: z.ZodOptional<z.ZodObject<{
93
+ success: z.ZodBoolean;
94
+ message: z.ZodOptional<z.ZodString>;
95
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
96
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
97
+ success: z.ZodBoolean;
98
+ message: z.ZodOptional<z.ZodString>;
99
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
100
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
101
+ success: z.ZodBoolean;
102
+ message: z.ZodOptional<z.ZodString>;
103
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
104
+ }, z.ZodTypeAny, "passthrough">>>;
105
+ /** After this date the action can no longer be executed */
106
+ expires_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
107
+ created_by: z.ZodObject<{
108
+ type: z.ZodEnum<["system", "human"]>;
109
+ user_id: z.ZodOptional<z.ZodString>;
110
+ module: z.ZodOptional<z.ZodString>;
111
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
112
+ type: z.ZodEnum<["system", "human"]>;
113
+ user_id: z.ZodOptional<z.ZodString>;
114
+ module: z.ZodOptional<z.ZodString>;
115
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
116
+ type: z.ZodEnum<["system", "human"]>;
117
+ user_id: z.ZodOptional<z.ZodString>;
118
+ module: z.ZodOptional<z.ZodString>;
119
+ }, z.ZodTypeAny, "passthrough">>;
120
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
121
+ id: z.ZodString;
122
+ ref: z.ZodAny;
123
+ tenant: z.ZodString;
124
+ model_ver: z.ZodDefault<z.ZodNumber>;
125
+ created_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
126
+ updated_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
127
+ deleted_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
128
+ } & {
129
+ /** Action to execute (e.g. confirm_appointment, cancel_appointment...) */
130
+ action_type: z.ZodString;
131
+ /** Full action data the executor needs (never leaves the backend) */
132
+ action_payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
133
+ recipient: z.ZodObject<{
134
+ contact_id: z.ZodOptional<z.ZodString>;
135
+ lead_id: z.ZodOptional<z.ZodString>;
136
+ patient_id: z.ZodOptional<z.ZodString>;
137
+ address: z.ZodString;
138
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
139
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
140
+ contact_id: z.ZodOptional<z.ZodString>;
141
+ lead_id: z.ZodOptional<z.ZodString>;
142
+ patient_id: z.ZodOptional<z.ZodString>;
143
+ address: z.ZodString;
144
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
145
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
146
+ contact_id: z.ZodOptional<z.ZodString>;
147
+ lead_id: z.ZodOptional<z.ZodString>;
148
+ patient_id: z.ZodOptional<z.ZodString>;
149
+ address: z.ZodString;
150
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
151
+ }, z.ZodTypeAny, "passthrough">>;
152
+ /** Link to the notification message that delivered this action */
153
+ notification_message_id: z.ZodOptional<z.ZodString>;
154
+ template_name: z.ZodOptional<z.ZodString>;
155
+ button_index: z.ZodOptional<z.ZodNumber>;
156
+ button_label: z.ZodOptional<z.ZodString>;
157
+ /** Link to evo-chat thread/ticket (for timeline events) */
158
+ thread_id: z.ZodOptional<z.ZodString>;
159
+ ticket_id: z.ZodOptional<z.ZodString>;
160
+ status: z.ZodEnum<["pending", "executed", "expired", "cancelled", "failed"]>;
161
+ executed_at: z.ZodOptional<z.ZodDate>;
162
+ executed_by: z.ZodOptional<z.ZodString>;
163
+ executed_result: z.ZodOptional<z.ZodObject<{
164
+ success: z.ZodBoolean;
165
+ message: z.ZodOptional<z.ZodString>;
166
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
167
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
168
+ success: z.ZodBoolean;
169
+ message: z.ZodOptional<z.ZodString>;
170
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
171
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
172
+ success: z.ZodBoolean;
173
+ message: z.ZodOptional<z.ZodString>;
174
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
175
+ }, z.ZodTypeAny, "passthrough">>>;
176
+ /** After this date the action can no longer be executed */
177
+ expires_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
178
+ created_by: z.ZodObject<{
179
+ type: z.ZodEnum<["system", "human"]>;
180
+ user_id: z.ZodOptional<z.ZodString>;
181
+ module: z.ZodOptional<z.ZodString>;
182
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
183
+ type: z.ZodEnum<["system", "human"]>;
184
+ user_id: z.ZodOptional<z.ZodString>;
185
+ module: z.ZodOptional<z.ZodString>;
186
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
187
+ type: z.ZodEnum<["system", "human"]>;
188
+ user_id: z.ZodOptional<z.ZodString>;
189
+ module: z.ZodOptional<z.ZodString>;
190
+ }, z.ZodTypeAny, "passthrough">>;
191
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
192
+ id: z.ZodString;
193
+ ref: z.ZodAny;
194
+ tenant: z.ZodString;
195
+ model_ver: z.ZodDefault<z.ZodNumber>;
196
+ created_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
197
+ updated_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
198
+ deleted_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
199
+ } & {
200
+ /** Action to execute (e.g. confirm_appointment, cancel_appointment...) */
201
+ action_type: z.ZodString;
202
+ /** Full action data the executor needs (never leaves the backend) */
203
+ action_payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
204
+ recipient: z.ZodObject<{
205
+ contact_id: z.ZodOptional<z.ZodString>;
206
+ lead_id: z.ZodOptional<z.ZodString>;
207
+ patient_id: z.ZodOptional<z.ZodString>;
208
+ address: z.ZodString;
209
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
210
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
211
+ contact_id: z.ZodOptional<z.ZodString>;
212
+ lead_id: z.ZodOptional<z.ZodString>;
213
+ patient_id: z.ZodOptional<z.ZodString>;
214
+ address: z.ZodString;
215
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
216
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
217
+ contact_id: z.ZodOptional<z.ZodString>;
218
+ lead_id: z.ZodOptional<z.ZodString>;
219
+ patient_id: z.ZodOptional<z.ZodString>;
220
+ address: z.ZodString;
221
+ kind: z.ZodEnum<["whatsapp", "email", "sms"]>;
222
+ }, z.ZodTypeAny, "passthrough">>;
223
+ /** Link to the notification message that delivered this action */
224
+ notification_message_id: z.ZodOptional<z.ZodString>;
225
+ template_name: z.ZodOptional<z.ZodString>;
226
+ button_index: z.ZodOptional<z.ZodNumber>;
227
+ button_label: z.ZodOptional<z.ZodString>;
228
+ /** Link to evo-chat thread/ticket (for timeline events) */
229
+ thread_id: z.ZodOptional<z.ZodString>;
230
+ ticket_id: z.ZodOptional<z.ZodString>;
231
+ status: z.ZodEnum<["pending", "executed", "expired", "cancelled", "failed"]>;
232
+ executed_at: z.ZodOptional<z.ZodDate>;
233
+ executed_by: z.ZodOptional<z.ZodString>;
234
+ executed_result: z.ZodOptional<z.ZodObject<{
235
+ success: z.ZodBoolean;
236
+ message: z.ZodOptional<z.ZodString>;
237
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
238
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
239
+ success: z.ZodBoolean;
240
+ message: z.ZodOptional<z.ZodString>;
241
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
242
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
243
+ success: z.ZodBoolean;
244
+ message: z.ZodOptional<z.ZodString>;
245
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
246
+ }, z.ZodTypeAny, "passthrough">>>;
247
+ /** After this date the action can no longer be executed */
248
+ expires_at: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
249
+ created_by: z.ZodObject<{
250
+ type: z.ZodEnum<["system", "human"]>;
251
+ user_id: z.ZodOptional<z.ZodString>;
252
+ module: z.ZodOptional<z.ZodString>;
253
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
254
+ type: z.ZodEnum<["system", "human"]>;
255
+ user_id: z.ZodOptional<z.ZodString>;
256
+ module: z.ZodOptional<z.ZodString>;
257
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
258
+ type: z.ZodEnum<["system", "human"]>;
259
+ user_id: z.ZodOptional<z.ZodString>;
260
+ module: z.ZodOptional<z.ZodString>;
261
+ }, z.ZodTypeAny, "passthrough">>;
262
+ }, z.ZodTypeAny, "passthrough">>;
263
+ export type IQuickReplyAction = z.infer<typeof zQuickReplyActionSchema>;
264
+ export declare const zQuickReplyActionIntentSchema: z.ZodObject<{
265
+ action_type: z.ZodString;
266
+ action_payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
267
+ button_index: z.ZodNumber;
268
+ button_label: z.ZodString;
269
+ expires_at: z.ZodOptional<z.ZodDate>;
270
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
271
+ action_type: z.ZodString;
272
+ action_payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
273
+ button_index: z.ZodNumber;
274
+ button_label: z.ZodString;
275
+ expires_at: z.ZodOptional<z.ZodDate>;
276
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
277
+ action_type: z.ZodString;
278
+ action_payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
279
+ button_index: z.ZodNumber;
280
+ button_label: z.ZodString;
281
+ expires_at: z.ZodOptional<z.ZodDate>;
282
+ }, z.ZodTypeAny, "passthrough">>;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.zQuickReplyActionIntentSchema = exports.zQuickReplyActionSchema = exports.zQuickReplyActionCreatedBySchema = exports.zQuickReplyActionResultSchema = exports.zQuickReplyActionRecipientSchema = exports.zQuickReplyActionStatusSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const zod_schemas_1 = require("../../shared/zod-schemas");
6
+ // ======================================================
7
+ // Quick-Reply Actions — cross-channel actionable buttons/links
8
+ //
9
+ // Doc path: tenants/{tenant}/apps/evo-notifications/quick-reply-actions/{actionId}
10
+ //
11
+ // The button/link carries ONLY the short actionId; the full action data
12
+ // (action_type + action_payload) stays in this Firestore document.
13
+ // Single-use (status=executed), expirable (expires_at), auditable.
14
+ // See cloud-functions/docs/plan-quick-reply-actions.md (§4, §9).
15
+ // ======================================================
16
+ // ---- Status enum ----
17
+ exports.zQuickReplyActionStatusSchema = zod_1.z.enum([
18
+ "pending",
19
+ "executed",
20
+ "expired",
21
+ "cancelled",
22
+ "failed",
23
+ ]);
24
+ // ---- Recipient (where the action was delivered) ----
25
+ exports.zQuickReplyActionRecipientSchema = zod_1.z
26
+ .object({
27
+ contact_id: zod_1.z.string().optional(), // evo-chat contact id
28
+ lead_id: zod_1.z.string().optional(), // evo-crm lead id
29
+ patient_id: zod_1.z.string().optional(), // evo-med patient id
30
+ address: zod_1.z.string(), // phone or email
31
+ kind: zod_1.z.enum(["whatsapp", "email", "sms"]),
32
+ })
33
+ .passthrough();
34
+ // ---- Execution result (filled when status=executed/failed) ----
35
+ exports.zQuickReplyActionResultSchema = zod_1.z
36
+ .object({
37
+ success: zod_1.z.boolean(),
38
+ message: zod_1.z.string().optional(), // message shown to the patient
39
+ data: zod_1.z.record(zod_1.z.unknown()).optional(),
40
+ })
41
+ .passthrough();
42
+ // ---- Audit: who created the action ----
43
+ exports.zQuickReplyActionCreatedBySchema = zod_1.z
44
+ .object({
45
+ type: zod_1.z.enum(["system", "human"]),
46
+ user_id: zod_1.z.string().optional(),
47
+ module: zod_1.z.string().optional(), // 'evo-med', 'evo-finops', 'evo-notifications'...
48
+ })
49
+ .passthrough();
50
+ // ---- Main document schema ----
51
+ exports.zQuickReplyActionSchema = zod_schemas_1.zFireDocSchema
52
+ .extend({
53
+ /** Action to execute (e.g. confirm_appointment, cancel_appointment...) */
54
+ action_type: zod_1.z.string(),
55
+ /** Full action data the executor needs (never leaves the backend) */
56
+ action_payload: zod_1.z.record(zod_1.z.unknown()),
57
+ recipient: exports.zQuickReplyActionRecipientSchema,
58
+ /** Link to the notification message that delivered this action */
59
+ notification_message_id: zod_1.z.string().optional(),
60
+ template_name: zod_1.z.string().optional(),
61
+ button_index: zod_1.z.number().optional(),
62
+ button_label: zod_1.z.string().optional(),
63
+ /** Link to evo-chat thread/ticket (for timeline events) */
64
+ thread_id: zod_1.z.string().optional(),
65
+ ticket_id: zod_1.z.string().optional(),
66
+ status: exports.zQuickReplyActionStatusSchema,
67
+ executed_at: zod_1.z.coerce.date().optional(),
68
+ executed_by: zod_1.z.string().optional(), // whatsapp_button | email_link | sms_link | manual
69
+ executed_result: exports.zQuickReplyActionResultSchema.optional(),
70
+ /** After this date the action can no longer be executed */
71
+ expires_at: zod_1.z.coerce.date().nullable().optional(),
72
+ created_by: exports.zQuickReplyActionCreatedBySchema,
73
+ })
74
+ .passthrough();
75
+ // ---- Send-payload sub-schema: one quick-reply action intent ----
76
+ // This is the channel-agnostic INTENT carried in the notification send payload.
77
+ // Each provider renders it per channel (WhatsApp -> button payload; email/SMS -> /qr link).
78
+ exports.zQuickReplyActionIntentSchema = zod_1.z
79
+ .object({
80
+ action_type: zod_1.z.string(),
81
+ action_payload: zod_1.z.record(zod_1.z.unknown()),
82
+ button_index: zod_1.z.number(),
83
+ button_label: zod_1.z.string(),
84
+ expires_at: zod_1.z.coerce.date().optional(),
85
+ })
86
+ .passthrough();
87
+ // NB: the canonical TS interface `IQuickReplyActionIntent` lives in
88
+ // types/evo-notifications/index.ts (hand-written). We deliberately do NOT
89
+ // re-export a z.infer alias of the same name here to avoid a duplicate-export
90
+ // collision through the package root index.
@@ -0,0 +1,106 @@
1
+ import { z } from "zod";
2
+ import { zFireDocSchema } from "../../shared/zod-schemas";
3
+
4
+ // ======================================================
5
+ // Quick-Reply Actions — cross-channel actionable buttons/links
6
+ //
7
+ // Doc path: tenants/{tenant}/apps/evo-notifications/quick-reply-actions/{actionId}
8
+ //
9
+ // The button/link carries ONLY the short actionId; the full action data
10
+ // (action_type + action_payload) stays in this Firestore document.
11
+ // Single-use (status=executed), expirable (expires_at), auditable.
12
+ // See cloud-functions/docs/plan-quick-reply-actions.md (§4, §9).
13
+ // ======================================================
14
+
15
+ // ---- Status enum ----
16
+ export const zQuickReplyActionStatusSchema = z.enum([
17
+ "pending",
18
+ "executed",
19
+ "expired",
20
+ "cancelled",
21
+ "failed",
22
+ ]);
23
+ export type IQuickReplyActionStatus = z.infer<
24
+ typeof zQuickReplyActionStatusSchema
25
+ >;
26
+
27
+ // ---- Recipient (where the action was delivered) ----
28
+ export const zQuickReplyActionRecipientSchema = z
29
+ .object({
30
+ contact_id: z.string().optional(), // evo-chat contact id
31
+ lead_id: z.string().optional(), // evo-crm lead id
32
+ patient_id: z.string().optional(), // evo-med patient id
33
+ address: z.string(), // phone or email
34
+ kind: z.enum(["whatsapp", "email", "sms"]),
35
+ })
36
+ .passthrough();
37
+
38
+ // ---- Execution result (filled when status=executed/failed) ----
39
+ export const zQuickReplyActionResultSchema = z
40
+ .object({
41
+ success: z.boolean(),
42
+ message: z.string().optional(), // message shown to the patient
43
+ data: z.record(z.unknown()).optional(),
44
+ })
45
+ .passthrough();
46
+
47
+ // ---- Audit: who created the action ----
48
+ export const zQuickReplyActionCreatedBySchema = z
49
+ .object({
50
+ type: z.enum(["system", "human"]),
51
+ user_id: z.string().optional(),
52
+ module: z.string().optional(), // 'evo-med', 'evo-finops', 'evo-notifications'...
53
+ })
54
+ .passthrough();
55
+
56
+ // ---- Main document schema ----
57
+ export const zQuickReplyActionSchema = zFireDocSchema
58
+ .extend({
59
+ /** Action to execute (e.g. confirm_appointment, cancel_appointment...) */
60
+ action_type: z.string(),
61
+ /** Full action data the executor needs (never leaves the backend) */
62
+ action_payload: z.record(z.unknown()),
63
+ recipient: zQuickReplyActionRecipientSchema,
64
+
65
+ /** Link to the notification message that delivered this action */
66
+ notification_message_id: z.string().optional(),
67
+ template_name: z.string().optional(),
68
+ button_index: z.number().optional(),
69
+ button_label: z.string().optional(),
70
+
71
+ /** Link to evo-chat thread/ticket (for timeline events) */
72
+ thread_id: z.string().optional(),
73
+ ticket_id: z.string().optional(),
74
+
75
+ status: zQuickReplyActionStatusSchema,
76
+
77
+ executed_at: z.coerce.date().optional(),
78
+ executed_by: z.string().optional(), // whatsapp_button | email_link | sms_link | manual
79
+ executed_result: zQuickReplyActionResultSchema.optional(),
80
+
81
+ /** After this date the action can no longer be executed */
82
+ expires_at: z.coerce.date().nullable().optional(),
83
+
84
+ created_by: zQuickReplyActionCreatedBySchema,
85
+ })
86
+ .passthrough();
87
+
88
+ export type IQuickReplyAction = z.infer<typeof zQuickReplyActionSchema>;
89
+
90
+ // ---- Send-payload sub-schema: one quick-reply action intent ----
91
+ // This is the channel-agnostic INTENT carried in the notification send payload.
92
+ // Each provider renders it per channel (WhatsApp -> button payload; email/SMS -> /qr link).
93
+ export const zQuickReplyActionIntentSchema = z
94
+ .object({
95
+ action_type: z.string(),
96
+ action_payload: z.record(z.unknown()),
97
+ button_index: z.number(),
98
+ button_label: z.string(),
99
+ expires_at: z.coerce.date().optional(),
100
+ })
101
+ .passthrough();
102
+
103
+ // NB: the canonical TS interface `IQuickReplyActionIntent` lives in
104
+ // types/evo-notifications/index.ts (hand-written). We deliberately do NOT
105
+ // re-export a z.infer alias of the same name here to avoid a duplicate-export
106
+ // collision through the package root index.