placementt-core 1.400.877 → 1.400.878
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/lib/customerCareConfig.d.ts +45 -0
- package/lib/customerCareConfig.js +87 -0
- package/lib/customerCareConfig.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/typeDefinitions.d.ts +7 -4
- package/package.json +1 -1
- package/src/customerCareConfig.ts +123 -0
- package/src/index.ts +1 -0
- package/src/typeDefinitions.ts +7 -4
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type PhoneCheckInRule = {
|
|
2
|
+
intervalDays: number;
|
|
3
|
+
label: string;
|
|
4
|
+
};
|
|
5
|
+
export type SeasonalTaskConfig = {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
deadlineMMDD: string;
|
|
9
|
+
createAtMMDD: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
export type BlackoutPeriod = {
|
|
13
|
+
start: string;
|
|
14
|
+
end: string;
|
|
15
|
+
label: string;
|
|
16
|
+
};
|
|
17
|
+
export type ChecklistItemStatus = "waiting" | "packed" | "shipped";
|
|
18
|
+
export type ChecklistItem = {
|
|
19
|
+
oId: string;
|
|
20
|
+
name: string;
|
|
21
|
+
status: ChecklistItemStatus;
|
|
22
|
+
};
|
|
23
|
+
export type PhoneCheckInCategory = "careersHub" | "trust" | "workExperience" | "employerEvents" | null;
|
|
24
|
+
export type CustomerCareConfig = {
|
|
25
|
+
seasonalTasks: SeasonalTaskConfig[];
|
|
26
|
+
phoneCheckIn: {
|
|
27
|
+
careersHub: PhoneCheckInRule;
|
|
28
|
+
trust: PhoneCheckInRule;
|
|
29
|
+
workExperience: PhoneCheckInRule;
|
|
30
|
+
employerEvents: PhoneCheckInRule;
|
|
31
|
+
};
|
|
32
|
+
blackoutPeriods: BlackoutPeriod[];
|
|
33
|
+
};
|
|
34
|
+
export declare const customerCareConfig: CustomerCareConfig;
|
|
35
|
+
export declare function resolveSeasonalDates(cfg: SeasonalTaskConfig): {
|
|
36
|
+
createAt: Date;
|
|
37
|
+
deadline: Date;
|
|
38
|
+
taskTag: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function isInBlackout(date: Date, blackouts: BlackoutPeriod[]): BlackoutPeriod | null;
|
|
41
|
+
export declare function getCheckInCategory(ins: {
|
|
42
|
+
package: string;
|
|
43
|
+
workExperience?: boolean;
|
|
44
|
+
employerEvents?: boolean;
|
|
45
|
+
}): PhoneCheckInCategory;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.customerCareConfig = void 0;
|
|
4
|
+
exports.resolveSeasonalDates = resolveSeasonalDates;
|
|
5
|
+
exports.isInBlackout = isInBlackout;
|
|
6
|
+
exports.getCheckInCategory = getCheckInCategory;
|
|
7
|
+
exports.customerCareConfig = {
|
|
8
|
+
seasonalTasks: [
|
|
9
|
+
{
|
|
10
|
+
id: "christmasCards",
|
|
11
|
+
name: "Christmas Cards",
|
|
12
|
+
deadlineMMDD: "12-12",
|
|
13
|
+
createAtMMDD: "11-28",
|
|
14
|
+
description: "Send Christmas cards to admin staff at every active school.",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
// Easter moves ~1–2 weeks each year; update createAtMMDD / deadlineMMDD as needed.
|
|
18
|
+
id: "easterEggs",
|
|
19
|
+
name: "Easter Eggs",
|
|
20
|
+
deadlineMMDD: "03-27",
|
|
21
|
+
createAtMMDD: "03-09",
|
|
22
|
+
description: "Send Easter eggs to admin staff at every active school.",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
phoneCheckIn: {
|
|
26
|
+
careersHub: { intervalDays: 42, label: "Careers Hub" },
|
|
27
|
+
trust: { intervalDays: 56, label: "Trust" },
|
|
28
|
+
workExperience: { intervalDays: 56, label: "Work Experience" },
|
|
29
|
+
employerEvents: { intervalDays: 70, label: "Employer Events" },
|
|
30
|
+
},
|
|
31
|
+
// UK school term blackout periods (MM-DD, approximate national averages)
|
|
32
|
+
blackoutPeriods: [
|
|
33
|
+
{ start: "07-18", end: "09-01", label: "Summer holidays" },
|
|
34
|
+
{ start: "10-20", end: "10-31", label: "October half-term" },
|
|
35
|
+
{ start: "12-22", end: "01-05", label: "Christmas holidays" },
|
|
36
|
+
{ start: "02-16", end: "02-20", label: "February half-term" },
|
|
37
|
+
// Easter window – adjust if Easter falls unusually early or late
|
|
38
|
+
{ start: "03-28", end: "04-14", label: "Easter holidays" },
|
|
39
|
+
{ start: "05-25", end: "05-29", label: "May half-term" },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
function mmddToDate(mmdd, year) {
|
|
43
|
+
const [month, day] = mmdd.split("-").map(Number);
|
|
44
|
+
return new Date(year, month - 1, day);
|
|
45
|
+
}
|
|
46
|
+
function resolveSeasonalDates(cfg) {
|
|
47
|
+
const now = new Date();
|
|
48
|
+
const year = now.getFullYear();
|
|
49
|
+
let createAt = mmddToDate(cfg.createAtMMDD, year);
|
|
50
|
+
let deadline = mmddToDate(cfg.deadlineMMDD, year);
|
|
51
|
+
// If we're already past this year's deadline, resolve to next year
|
|
52
|
+
if (now > deadline) {
|
|
53
|
+
createAt = mmddToDate(cfg.createAtMMDD, year + 1);
|
|
54
|
+
deadline = mmddToDate(cfg.deadlineMMDD, year + 1);
|
|
55
|
+
return { createAt, deadline, taskTag: `${cfg.id}_${year + 1}` };
|
|
56
|
+
}
|
|
57
|
+
return { createAt, deadline, taskTag: `${cfg.id}_${year}` };
|
|
58
|
+
}
|
|
59
|
+
function isInBlackout(date, blackouts) {
|
|
60
|
+
const month = date.getMonth() + 1;
|
|
61
|
+
const day = date.getDate();
|
|
62
|
+
const mmdd = `${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
63
|
+
for (const b of blackouts) {
|
|
64
|
+
if (b.start <= b.end) {
|
|
65
|
+
if (mmdd >= b.start && mmdd <= b.end)
|
|
66
|
+
return b;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Wraps year boundary (e.g. 12-22 to 01-05)
|
|
70
|
+
if (mmdd >= b.start || mmdd <= b.end)
|
|
71
|
+
return b;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function getCheckInCategory(ins) {
|
|
77
|
+
if (ins.package === "careersHub")
|
|
78
|
+
return "careersHub";
|
|
79
|
+
if (ins.package === "institutes-two")
|
|
80
|
+
return "trust";
|
|
81
|
+
if (ins.package === "institutes-one" && ins.workExperience)
|
|
82
|
+
return "workExperience";
|
|
83
|
+
if (ins.package === "institutes-one" && ins.employerEvents)
|
|
84
|
+
return "employerEvents";
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=customerCareConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customerCareConfig.js","sourceRoot":"","sources":["../src/customerCareConfig.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./firebase/callableJobContext";
|
|
|
3
3
|
export * from "./firebase/readDatabase";
|
|
4
4
|
export * from "./firebase/writeDatabase";
|
|
5
5
|
export * from "./firebase/util";
|
|
6
|
+
export * from "./customerCareConfig";
|
|
6
7
|
export * from "./firebase/firebaseConfig";
|
|
7
8
|
export * from "./firebase/firebaseQuery";
|
|
8
9
|
export * from "./typeDefinitions";
|
package/lib/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __exportStar(require("./firebase/callableJobContext"), exports);
|
|
|
23
23
|
__exportStar(require("./firebase/readDatabase"), exports);
|
|
24
24
|
__exportStar(require("./firebase/writeDatabase"), exports);
|
|
25
25
|
__exportStar(require("./firebase/util"), exports);
|
|
26
|
+
__exportStar(require("./customerCareConfig"), exports);
|
|
26
27
|
__exportStar(require("./firebase/firebaseConfig"), exports);
|
|
27
28
|
__exportStar(require("./firebase/firebaseQuery"), exports);
|
|
28
29
|
__exportStar(require("./typeDefinitions"), exports);
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AACA,sDAAoC;AACpC,gEAA8C;AAC9C,0DAAwC;AACxC,2DAAyC;AACzC,kDAAgC;AAChC,4DAA0C;AAC1C,2DAAyC;AAEzC,oDAAkC;AAClC,kDAAgC;AAChC,uDAAqC;AACrC,iDAA+B;AAC/B,8CAA4B;AAC5B,0CAAwB;AACxB,yCAAuB;AACvB,4DAA0C;AAC1C,kDAAgC;AAChC,iDAA+B;AAC/B,2CAAyB;AACzB,4DAA0C;AAC1C,oEAAiD;AACjD,yEAAuD;AACvD,kEAAgD;AAChD,kEAAgD;AAChD,oEAAkD;AAClD,yGAAuF;AACvF,0GAAwF;AACxF,+FAA6E;AAC7E,4DAA0C;AAC1C,oEAAkD;AAClD,gEAA8C;AAC9C,2EAAyD;AACzD,6CAA2B;AAC3B,+CAA6B;AAC7B,6DAAuE;AAA9D,2IAAA,OAAO,OAAuB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AACA,sDAAoC;AACpC,gEAA8C;AAC9C,0DAAwC;AACxC,2DAAyC;AACzC,kDAAgC;AAChC,uDAAqC;AACrC,4DAA0C;AAC1C,2DAAyC;AAEzC,oDAAkC;AAClC,kDAAgC;AAChC,uDAAqC;AACrC,iDAA+B;AAC/B,8CAA4B;AAC5B,0CAAwB;AACxB,yCAAuB;AACvB,4DAA0C;AAC1C,kDAAgC;AAChC,iDAA+B;AAC/B,2CAAyB;AACzB,4DAA0C;AAC1C,oEAAiD;AACjD,yEAAuD;AACvD,kEAAgD;AAChD,kEAAgD;AAChD,oEAAkD;AAClD,yGAAuF;AACvF,0GAAwF;AACxF,+FAA6E;AAC7E,4DAA0C;AAC1C,oEAAkD;AAClD,gEAA8C;AAC9C,2EAAyD;AACzD,6CAA2B;AAC3B,+CAA6B;AAC7B,6DAAuE;AAA9D,2IAAA,OAAO,OAAuB"}
|
package/lib/typeDefinitions.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DocumentData, DocumentReference, OrderByDirection, Timestamp, WhereFilterOp } from "firebase/firestore";
|
|
2
2
|
import { Descendant } from "slate";
|
|
3
3
|
import { emailTemplates, skillLabelColours } from "./constants";
|
|
4
|
+
import type { ChecklistItem } from "./customerCareConfig";
|
|
4
5
|
export type FilterObject = {
|
|
5
6
|
[key: string]: {
|
|
6
7
|
label: string;
|
|
@@ -2453,9 +2454,9 @@ export type Communication = {
|
|
|
2453
2454
|
lastMessageDirection?: "inbound" | "outbound";
|
|
2454
2455
|
};
|
|
2455
2456
|
export type SupportTask = {
|
|
2456
|
-
uid
|
|
2457
|
+
uid?: string;
|
|
2457
2458
|
oId?: string;
|
|
2458
|
-
email
|
|
2459
|
+
email?: string;
|
|
2459
2460
|
title: string;
|
|
2460
2461
|
description?: string;
|
|
2461
2462
|
createdAt: string;
|
|
@@ -2464,10 +2465,12 @@ export type SupportTask = {
|
|
|
2464
2465
|
assignee: string;
|
|
2465
2466
|
commId?: string;
|
|
2466
2467
|
commType?: "leads" | "users";
|
|
2467
|
-
source?: "customerQuery" | "general";
|
|
2468
|
+
source?: "customerQuery" | "general" | "seasonalTask";
|
|
2468
2469
|
dueAt: string;
|
|
2469
|
-
inbox
|
|
2470
|
+
inbox?: SupportInbox;
|
|
2470
2471
|
messageId?: string;
|
|
2472
|
+
checklist?: ChecklistItem[];
|
|
2473
|
+
taskTag?: string;
|
|
2471
2474
|
};
|
|
2472
2475
|
export type SupportInbox = "oneDay" | "threeDay" | "oneWeek";
|
|
2473
2476
|
export type CustomerProductType = "careersHub" | "careersHubSchool" | "workExperience" | "trust" | "employerEvents";
|
package/package.json
CHANGED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
export type PhoneCheckInRule = {
|
|
2
|
+
intervalDays: number;
|
|
3
|
+
label: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
// Dates stored as "MM-DD" and resolved against the current (or next) year at runtime.
|
|
7
|
+
// Easter moves each year; the approximate fixed date can be updated as needed.
|
|
8
|
+
export type SeasonalTaskConfig = {
|
|
9
|
+
id: string; // e.g. "christmasCards" – year is appended at runtime
|
|
10
|
+
name: string; // e.g. "Christmas Cards"
|
|
11
|
+
deadlineMMDD: string; // "MM-DD" – must be sent by this date
|
|
12
|
+
createAtMMDD: string; // "MM-DD" – when the task becomes actionable
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type BlackoutPeriod = {
|
|
17
|
+
start: string; // "MM-DD"
|
|
18
|
+
end: string; // "MM-DD" (wraps into next year if start > end, e.g. Dec–Jan)
|
|
19
|
+
label: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type ChecklistItemStatus = "waiting" | "packed" | "shipped";
|
|
23
|
+
|
|
24
|
+
export type ChecklistItem = {
|
|
25
|
+
oId: string;
|
|
26
|
+
name: string;
|
|
27
|
+
status: ChecklistItemStatus;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type PhoneCheckInCategory = "careersHub" | "trust" | "workExperience" | "employerEvents" | null;
|
|
31
|
+
|
|
32
|
+
export type CustomerCareConfig = {
|
|
33
|
+
seasonalTasks: SeasonalTaskConfig[];
|
|
34
|
+
phoneCheckIn: {
|
|
35
|
+
careersHub: PhoneCheckInRule;
|
|
36
|
+
trust: PhoneCheckInRule;
|
|
37
|
+
workExperience: PhoneCheckInRule;
|
|
38
|
+
employerEvents: PhoneCheckInRule;
|
|
39
|
+
};
|
|
40
|
+
blackoutPeriods: BlackoutPeriod[];
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const customerCareConfig: CustomerCareConfig = {
|
|
44
|
+
seasonalTasks: [
|
|
45
|
+
{
|
|
46
|
+
id: "christmasCards",
|
|
47
|
+
name: "Christmas Cards",
|
|
48
|
+
deadlineMMDD: "12-12",
|
|
49
|
+
createAtMMDD: "11-28",
|
|
50
|
+
description: "Send Christmas cards to admin staff at every active school.",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
// Easter moves ~1–2 weeks each year; update createAtMMDD / deadlineMMDD as needed.
|
|
54
|
+
id: "easterEggs",
|
|
55
|
+
name: "Easter Eggs",
|
|
56
|
+
deadlineMMDD: "03-27",
|
|
57
|
+
createAtMMDD: "03-09",
|
|
58
|
+
description: "Send Easter eggs to admin staff at every active school.",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
phoneCheckIn: {
|
|
62
|
+
careersHub: {intervalDays: 42, label: "Careers Hub"},
|
|
63
|
+
trust: {intervalDays: 56, label: "Trust"},
|
|
64
|
+
workExperience: {intervalDays: 56, label: "Work Experience"},
|
|
65
|
+
employerEvents: {intervalDays: 70, label: "Employer Events"},
|
|
66
|
+
},
|
|
67
|
+
// UK school term blackout periods (MM-DD, approximate national averages)
|
|
68
|
+
blackoutPeriods: [
|
|
69
|
+
{start: "07-18", end: "09-01", label: "Summer holidays"},
|
|
70
|
+
{start: "10-20", end: "10-31", label: "October half-term"},
|
|
71
|
+
{start: "12-22", end: "01-05", label: "Christmas holidays"},
|
|
72
|
+
{start: "02-16", end: "02-20", label: "February half-term"},
|
|
73
|
+
// Easter window – adjust if Easter falls unusually early or late
|
|
74
|
+
{start: "03-28", end: "04-14", label: "Easter holidays"},
|
|
75
|
+
{start: "05-25", end: "05-29", label: "May half-term"},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
function mmddToDate(mmdd: string, year: number): Date {
|
|
80
|
+
const [month, day] = mmdd.split("-").map(Number);
|
|
81
|
+
return new Date(year, month - 1, day);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function resolveSeasonalDates(cfg: SeasonalTaskConfig): {createAt: Date; deadline: Date; taskTag: string} {
|
|
85
|
+
const now = new Date();
|
|
86
|
+
const year = now.getFullYear();
|
|
87
|
+
|
|
88
|
+
let createAt = mmddToDate(cfg.createAtMMDD, year);
|
|
89
|
+
let deadline = mmddToDate(cfg.deadlineMMDD, year);
|
|
90
|
+
|
|
91
|
+
// If we're already past this year's deadline, resolve to next year
|
|
92
|
+
if (now > deadline) {
|
|
93
|
+
createAt = mmddToDate(cfg.createAtMMDD, year + 1);
|
|
94
|
+
deadline = mmddToDate(cfg.deadlineMMDD, year + 1);
|
|
95
|
+
return {createAt, deadline, taskTag: `${cfg.id}_${year + 1}`};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {createAt, deadline, taskTag: `${cfg.id}_${year}`};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function isInBlackout(date: Date, blackouts: BlackoutPeriod[]): BlackoutPeriod | null {
|
|
102
|
+
const month = date.getMonth() + 1;
|
|
103
|
+
const day = date.getDate();
|
|
104
|
+
const mmdd = `${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
105
|
+
|
|
106
|
+
for (const b of blackouts) {
|
|
107
|
+
if (b.start <= b.end) {
|
|
108
|
+
if (mmdd >= b.start && mmdd <= b.end) return b;
|
|
109
|
+
} else {
|
|
110
|
+
// Wraps year boundary (e.g. 12-22 to 01-05)
|
|
111
|
+
if (mmdd >= b.start || mmdd <= b.end) return b;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getCheckInCategory(ins: {package: string; workExperience?: boolean; employerEvents?: boolean}): PhoneCheckInCategory {
|
|
118
|
+
if (ins.package === "careersHub") return "careersHub";
|
|
119
|
+
if (ins.package === "institutes-two") return "trust";
|
|
120
|
+
if (ins.package === "institutes-one" && ins.workExperience) return "workExperience";
|
|
121
|
+
if (ins.package === "institutes-one" && ins.employerEvents) return "employerEvents";
|
|
122
|
+
return null;
|
|
123
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./firebase/callableJobContext";
|
|
|
4
4
|
export * from "./firebase/readDatabase";
|
|
5
5
|
export * from "./firebase/writeDatabase";
|
|
6
6
|
export * from "./firebase/util";
|
|
7
|
+
export * from "./customerCareConfig";
|
|
7
8
|
export * from "./firebase/firebaseConfig";
|
|
8
9
|
export * from "./firebase/firebaseQuery";
|
|
9
10
|
|
package/src/typeDefinitions.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {DocumentData, DocumentReference, OrderByDirection, Timestamp, WhereFilterOp} from "firebase/firestore";
|
|
2
2
|
import {Descendant} from "slate";
|
|
3
3
|
import {emailTemplates, skillLabelColours} from "./constants";
|
|
4
|
+
import type {ChecklistItem} from "./customerCareConfig";
|
|
4
5
|
|
|
5
6
|
export type FilterObject = {
|
|
6
7
|
[key: string]: {
|
|
@@ -2391,9 +2392,9 @@ export type Communication = {
|
|
|
2391
2392
|
};
|
|
2392
2393
|
|
|
2393
2394
|
export type SupportTask = {
|
|
2394
|
-
uid
|
|
2395
|
+
uid?: string; // user ID the task relates to (absent for non-user tasks)
|
|
2395
2396
|
oId?: string; // organisation ID, if the user has one
|
|
2396
|
-
email
|
|
2397
|
+
email?: string; // email address associated with the task (absent for non-user tasks)
|
|
2397
2398
|
title: string;
|
|
2398
2399
|
description?: string;
|
|
2399
2400
|
createdAt: string; // ISO string
|
|
@@ -2402,10 +2403,12 @@ export type SupportTask = {
|
|
|
2402
2403
|
assignee: string; // uid of the assigned team member
|
|
2403
2404
|
commId?: string; // optional link to a Communication doc
|
|
2404
2405
|
commType?: "leads" | "users"; // collection the comm lives in
|
|
2405
|
-
source?: "customerQuery" | "general";
|
|
2406
|
+
source?: "customerQuery" | "general" | "seasonalTask";
|
|
2406
2407
|
dueAt: string; // ISO string
|
|
2407
|
-
inbox
|
|
2408
|
+
inbox?: SupportInbox; // which task inbox triggered this (absent for non-email tasks)
|
|
2408
2409
|
messageId?: string; // Graph message ID — used to prevent duplicates
|
|
2410
|
+
checklist?: ChecklistItem[]; // school checklist for seasonalTask
|
|
2411
|
+
taskTag?: string; // deduplication key, e.g. "christmasCards_2026"
|
|
2409
2412
|
};
|
|
2410
2413
|
|
|
2411
2414
|
export type SupportInbox = "oneDay" | "threeDay" | "oneWeek";
|