@crimson-education/sdk 0.3.10 → 0.3.12

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.
@@ -1,6 +1,7 @@
1
1
  import type { CrimsonClientConfig } from "./types";
2
2
  import { MissionsApi } from "./missions";
3
3
  import { TasksApi } from "./tasks";
4
+ import { ReflectionsApi } from "./reflections";
4
5
  import { RoadmapApi } from "./roadmap";
5
6
  import { MissionLibraryApi } from "./missionLibrary";
6
7
  import { UsersApi } from "./users";
@@ -105,6 +106,7 @@ export declare class CrimsonClient {
105
106
  destroy(): void;
106
107
  missions: MissionsApi;
107
108
  tasks: TasksApi;
109
+ reflections: ReflectionsApi;
108
110
  roadmap: RoadmapApi;
109
111
  library: MissionLibraryApi;
110
112
  users: UsersApi;
@@ -13,6 +13,7 @@ exports.CrimsonClient = void 0;
13
13
  exports.createCrimsonClient = createCrimsonClient;
14
14
  const missions_1 = require("./missions");
15
15
  const tasks_1 = require("./tasks");
16
+ const reflections_1 = require("./reflections");
16
17
  const roadmap_1 = require("./roadmap");
17
18
  const missionLibrary_1 = require("./missionLibrary");
18
19
  const users_1 = require("./users");
@@ -48,6 +49,7 @@ class CrimsonClient {
48
49
  this.isResolvingDomain = false;
49
50
  this.missions = new missions_1.MissionsApi(this);
50
51
  this.tasks = new tasks_1.TasksApi(this);
52
+ this.reflections = new reflections_1.ReflectionsApi(this);
51
53
  this.roadmap = new roadmap_1.RoadmapApi(this);
52
54
  this.library = new missionLibrary_1.MissionLibraryApi(this);
53
55
  this.users = new users_1.UsersApi(this);
@@ -1,14 +1,18 @@
1
1
  import type { CrimsonClient } from "./client";
2
+ export type GradeTemplateType = "grade" | "general";
3
+ export type GradeTemplateGroup = "shared" | "custom";
4
+ export type GradeTemplateDivision = "US" | "UK";
2
5
  export interface GradeTemplateMission {
3
6
  id: string;
4
7
  gradeTemplateId: string;
5
8
  templateMissionId: string;
6
9
  startYearOffset?: number;
7
- startMonth: number;
10
+ startMonth?: number | null;
8
11
  startDay?: number;
9
12
  endYearOffset?: number;
10
- endMonth: number;
13
+ endMonth?: number | null;
11
14
  endDay?: number;
15
+ orderIndex?: number;
12
16
  createdAt: string;
13
17
  updatedAt: string;
14
18
  title?: string;
@@ -33,23 +37,30 @@ export interface GradeTemplateTask {
33
37
  }
34
38
  export interface CreateGradeTemplateMissionInput {
35
39
  templateMissionId: string;
40
+ tenantId?: string;
36
41
  startYearOffset?: number;
37
- startMonth: number;
42
+ startMonth?: number | null;
38
43
  startDay?: number;
39
44
  endYearOffset?: number;
40
- endMonth: number;
45
+ endMonth?: number | null;
41
46
  endDay?: number;
47
+ orderIndex?: number;
42
48
  }
43
49
  export interface GradeTemplateBrief {
44
50
  id: string;
45
51
  title: string;
46
- gradeLevel: number;
52
+ type?: GradeTemplateType;
53
+ division?: GradeTemplateDivision[] | null;
54
+ creatorId?: string;
55
+ group?: GradeTemplateGroup;
56
+ gradeLevel?: number | null;
47
57
  startYearOffset?: number;
48
- startMonth: number;
58
+ startMonth?: number | null;
49
59
  startDay?: number;
50
60
  endYearOffset?: number;
51
- endMonth: number;
61
+ endMonth?: number | null;
52
62
  endDay?: number;
63
+ numMissions?: number;
53
64
  }
54
65
  export interface GradeTemplate extends GradeTemplateBrief {
55
66
  missions: GradeTemplateMission[];
@@ -58,18 +69,27 @@ export interface GradeTemplate extends GradeTemplateBrief {
58
69
  }
59
70
  export interface CreateGradeTemplateInput {
60
71
  title: string;
61
- gradeLevel: number;
72
+ tenantId?: string;
73
+ type?: GradeTemplateType;
74
+ division?: GradeTemplateDivision[] | null;
75
+ creatorId?: string;
76
+ group?: GradeTemplateGroup;
77
+ gradeLevel?: number | null;
62
78
  startYearOffset?: number;
63
- startMonth: number;
79
+ startMonth?: number | null;
64
80
  startDay?: number;
65
81
  endYearOffset?: number;
66
- endMonth: number;
82
+ endMonth?: number | null;
67
83
  endDay?: number;
68
84
  }
69
85
  export interface GradeTemplateFilters {
70
86
  ids?: string[];
71
87
  startGrade?: number;
72
88
  endGrade?: number;
89
+ groups?: GradeTemplateGroup[];
90
+ type?: GradeTemplateType;
91
+ division?: GradeTemplateDivision[];
92
+ numMissions?: boolean;
73
93
  }
74
94
  export interface AddGradeTemplateToRoadmapInput {
75
95
  studentId: string;
@@ -81,13 +101,21 @@ export interface AddGradeTemplateToRoadmapInput {
81
101
  endDate?: string;
82
102
  }[];
83
103
  }
104
+ export interface AddGradeTemplateToRoadmapMissionResponse {
105
+ id: string;
106
+ isNew: boolean;
107
+ taskIds: string[];
108
+ }
109
+ export interface AddGradeTemplateToRoadmapResponse {
110
+ missions: AddGradeTemplateToRoadmapMissionResponse[];
111
+ }
84
112
  export declare class GradeTemplatesApi {
85
113
  private client;
86
114
  constructor(client: CrimsonClient);
87
115
  /**
88
116
  * List grade templates
89
117
  */
90
- listGradeTemplates(filters?: GradeTemplateFilters): Promise<GradeTemplate[]>;
118
+ listGradeTemplates(filters?: GradeTemplateFilters): Promise<GradeTemplateBrief[]>;
91
119
  /**
92
120
  * Get grade template by ID
93
121
  */
@@ -111,7 +139,5 @@ export declare class GradeTemplatesApi {
111
139
  /**
112
140
  * Add grade template to roadmap
113
141
  */
114
- addGradeTemplateToRoadmap(id: string, input: AddGradeTemplateToRoadmapInput): Promise<{
115
- success: boolean;
116
- }>;
142
+ addGradeTemplateToRoadmap(id: string, input: AddGradeTemplateToRoadmapInput): Promise<AddGradeTemplateToRoadmapResponse>;
117
143
  }
@@ -19,6 +19,7 @@ class GradeTemplatesApi {
19
19
  */
20
20
  listGradeTemplates(filters) {
21
21
  return __awaiter(this, void 0, void 0, function* () {
22
+ var _a, _b;
22
23
  const params = new URLSearchParams();
23
24
  if ((filters === null || filters === void 0 ? void 0 : filters.startGrade) !== undefined) {
24
25
  params.append("startgrade", String(filters.startGrade));
@@ -26,6 +27,18 @@ class GradeTemplatesApi {
26
27
  if ((filters === null || filters === void 0 ? void 0 : filters.endGrade) !== undefined) {
27
28
  params.append("endgrade", String(filters.endGrade));
28
29
  }
30
+ if ((_a = filters === null || filters === void 0 ? void 0 : filters.groups) === null || _a === void 0 ? void 0 : _a.length) {
31
+ params.append("groups", filters.groups.join(","));
32
+ }
33
+ if (filters === null || filters === void 0 ? void 0 : filters.type) {
34
+ params.append("type", filters.type);
35
+ }
36
+ if ((_b = filters === null || filters === void 0 ? void 0 : filters.division) === null || _b === void 0 ? void 0 : _b.length) {
37
+ params.append("division", filters.division.join(","));
38
+ }
39
+ if ((filters === null || filters === void 0 ? void 0 : filters.numMissions) !== undefined) {
40
+ params.append("numMissions", String(filters.numMissions));
41
+ }
29
42
  const query = params.toString();
30
43
  const path = query
31
44
  ? `/roadmap/grade-templates?${query}`
@@ -1,6 +1,7 @@
1
1
  export { CrimsonClient, createCrimsonClient } from "./client";
2
2
  export { MissionsApi } from "./missions";
3
3
  export { TasksApi, type TaskFilters, type TaskOrderBy } from "./tasks";
4
+ export { ReflectionsApi, type CreateReflectionInput, type UpdateReflectionInput, type BatchUpdateReflectionsInput, type ListReflectionsResponse, type GroupedMission, type ReflectionComment, type AddReflectionCommentInput } from "./reflections";
4
5
  export { RoadmapApi } from "./roadmap";
5
6
  export { MissionLibraryApi } from "./missionLibrary";
6
7
  export { UsersApi } from "./users";
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.generateState = exports.generateCodeChallenge = exports.generateCodeVerifier = exports.createDefaultTokenStorage = exports.MemoryTokenStorage = exports.SessionStorageTokenStorage = exports.LocalStorageTokenStorage = exports.TokenManager = exports.createCrimsonOAuthAdapter = exports.OAuthAdapter = exports.IndigoApi = exports.StudentProfileApi = exports.AccountApi = exports.UsersApi = exports.MissionLibraryApi = exports.RoadmapApi = exports.TasksApi = exports.MissionsApi = exports.createCrimsonClient = exports.CrimsonClient = void 0;
17
+ exports.generateState = exports.generateCodeChallenge = exports.generateCodeVerifier = exports.createDefaultTokenStorage = exports.MemoryTokenStorage = exports.SessionStorageTokenStorage = exports.LocalStorageTokenStorage = exports.TokenManager = exports.createCrimsonOAuthAdapter = exports.OAuthAdapter = exports.IndigoApi = exports.StudentProfileApi = exports.AccountApi = exports.UsersApi = exports.MissionLibraryApi = exports.RoadmapApi = exports.ReflectionsApi = exports.TasksApi = exports.MissionsApi = exports.createCrimsonClient = exports.CrimsonClient = void 0;
18
18
  var client_1 = require("./client");
19
19
  Object.defineProperty(exports, "CrimsonClient", { enumerable: true, get: function () { return client_1.CrimsonClient; } });
20
20
  Object.defineProperty(exports, "createCrimsonClient", { enumerable: true, get: function () { return client_1.createCrimsonClient; } });
@@ -22,6 +22,8 @@ var missions_1 = require("./missions");
22
22
  Object.defineProperty(exports, "MissionsApi", { enumerable: true, get: function () { return missions_1.MissionsApi; } });
23
23
  var tasks_1 = require("./tasks");
24
24
  Object.defineProperty(exports, "TasksApi", { enumerable: true, get: function () { return tasks_1.TasksApi; } });
25
+ var reflections_1 = require("./reflections");
26
+ Object.defineProperty(exports, "ReflectionsApi", { enumerable: true, get: function () { return reflections_1.ReflectionsApi; } });
25
27
  var roadmap_1 = require("./roadmap");
26
28
  Object.defineProperty(exports, "RoadmapApi", { enumerable: true, get: function () { return roadmap_1.RoadmapApi; } });
27
29
  var missionLibrary_1 = require("./missionLibrary");
@@ -6,6 +6,8 @@ export interface TemplateMissionFilters extends PaginationParams {
6
6
  groups?: string[];
7
7
  keyword?: string;
8
8
  userId?: string;
9
+ division?: string;
10
+ attr?: Record<string, any>;
9
11
  }
10
12
  export interface TemplateTaskFilters extends PaginationParams {
11
13
  categories?: string[];
@@ -20,11 +22,15 @@ export interface TemplateTaskUpdateInput {
20
22
  title?: string;
21
23
  description?: string;
22
24
  operation: string;
25
+ visibleSc?: boolean;
26
+ visibleRoadmap?: boolean;
23
27
  }
24
28
  export interface TemplateMissionUpdateInput {
25
29
  title?: string;
26
30
  description?: string;
27
31
  tasks?: TemplateTaskUpdateInput[];
32
+ visibleSc?: boolean;
33
+ visibleRoadmap?: boolean;
28
34
  }
29
35
  export interface CopyTemplateMissionInput {
30
36
  linkId: string;
@@ -44,10 +50,14 @@ export interface TemplateMissionCreateInput {
44
50
  description: string;
45
51
  category: string;
46
52
  subcategory: string;
53
+ visibleSc?: boolean;
54
+ visibleRoadmap?: boolean;
47
55
  tasks: {
48
56
  id?: string | null;
49
57
  description: string;
50
58
  content: string;
59
+ visibleSc?: boolean;
60
+ visibleRoadmap?: boolean;
51
61
  }[];
52
62
  }
53
63
  export interface AddTemplateMissionToRoadmapInput {
@@ -59,6 +69,11 @@ export interface AddTemplateMissionToRoadmapInput {
59
69
  taskIds?: string[];
60
70
  ignoreLink?: boolean;
61
71
  }
72
+ export interface AddTemplateMissionToRoadmapResponse {
73
+ missionId: string;
74
+ isNew: boolean;
75
+ taskIds: string[];
76
+ }
62
77
  export declare class MissionLibraryApi {
63
78
  private client;
64
79
  constructor(client: CrimsonClient);
@@ -102,11 +117,7 @@ export declare class MissionLibraryApi {
102
117
  /**
103
118
  * Add a template mission to a user's roadmap (create or update)
104
119
  */
105
- addToRoadmap(input: AddTemplateMissionToRoadmapInput): Promise<{
106
- missionId: string;
107
- isNew: boolean;
108
- updated: boolean;
109
- }>;
120
+ addToRoadmap(input: AddTemplateMissionToRoadmapInput): Promise<AddTemplateMissionToRoadmapResponse>;
110
121
  /**
111
122
  * Bulk assign missions from templates
112
123
  */
@@ -36,6 +36,12 @@ class MissionLibraryApi {
36
36
  if (filters === null || filters === void 0 ? void 0 : filters.userId) {
37
37
  params.append("userId", filters.userId);
38
38
  }
39
+ if (filters === null || filters === void 0 ? void 0 : filters.division) {
40
+ params.append("division", filters.division);
41
+ }
42
+ if (filters === null || filters === void 0 ? void 0 : filters.attr) {
43
+ params.append("attr", JSON.stringify(filters.attr));
44
+ }
39
45
  if ((filters === null || filters === void 0 ? void 0 : filters.start) !== undefined) {
40
46
  params.append("start", String(filters.start));
41
47
  }
@@ -167,11 +173,13 @@ class MissionLibraryApi {
167
173
  */
168
174
  updateTemplateMission(id, raw, update) {
169
175
  return __awaiter(this, void 0, void 0, function* () {
170
- var _a, _b;
176
+ var _a, _b, _c, _d;
171
177
  const data = {
172
178
  title: (_a = update.title) !== null && _a !== void 0 ? _a : raw.title,
173
179
  description: (_b = update.description) !== null && _b !== void 0 ? _b : raw.description,
174
180
  tasks: update.tasks || [],
181
+ visibleSc: (_c = update.visibleSc) !== null && _c !== void 0 ? _c : raw.visibleSc,
182
+ visibleRoadmap: (_d = update.visibleRoadmap) !== null && _d !== void 0 ? _d : raw.visibleRoadmap,
175
183
  // only allow updatecustom
176
184
  type: 'custom',
177
185
  category: raw.category,
@@ -0,0 +1,111 @@
1
+ import type { CrimsonClient } from "./client";
2
+ import type { Task } from "./types";
3
+ export interface ReflectionComment {
4
+ id: string;
5
+ category?: string;
6
+ content?: string;
7
+ creatorUid?: string;
8
+ creatorName?: string;
9
+ updatedAt?: string;
10
+ createdAt?: string;
11
+ }
12
+ export interface AddReflectionCommentInput {
13
+ content: string;
14
+ category?: string;
15
+ }
16
+ export interface CreateReflectionInput {
17
+ missionId: string;
18
+ description?: string;
19
+ startAt?: string;
20
+ dueDate?: string;
21
+ status?: string;
22
+ }
23
+ export interface UpdateReflectionInput {
24
+ missionId: string;
25
+ description?: string;
26
+ startAt?: string;
27
+ dueDate?: string;
28
+ status?: string;
29
+ }
30
+ export interface BatchUpdateReflectionsInput {
31
+ missionId: string;
32
+ status?: string;
33
+ startAt?: string;
34
+ dueDate?: string;
35
+ }
36
+ export interface GroupedMission {
37
+ mission: Task["mission"];
38
+ reflections: Task[];
39
+ latestReflectionAt: string;
40
+ }
41
+ export interface ListReflectionsResponse {
42
+ data: GroupedMission[];
43
+ pagination: {
44
+ total: number;
45
+ start: number;
46
+ limit: number;
47
+ hasMore: boolean;
48
+ };
49
+ }
50
+ export declare class ReflectionsApi {
51
+ private client;
52
+ constructor(client: CrimsonClient);
53
+ /**
54
+ * Get all reflections of a student, grouped by mission
55
+ */
56
+ list(params: {
57
+ studentId: string;
58
+ roadmapId?: string;
59
+ status?: string[];
60
+ description?: string;
61
+ /** how many missions to return */
62
+ limit?: number;
63
+ start?: number;
64
+ /** limit number of reflections returned per mission; default 1 */
65
+ perMissionLimit?: number;
66
+ }): Promise<ListReflectionsResponse>;
67
+ /**
68
+ * Get all reflections by mission ID
69
+ */
70
+ getByMission(missionId: string): Promise<Task[]>;
71
+ /**
72
+ * Create a new reflection for a mission
73
+ */
74
+ create(missionId: string, data: Omit<CreateReflectionInput, "missionId">): Promise<Task>;
75
+ /**
76
+ * Update an existing reflection by ID
77
+ */
78
+ update(id: string, data: UpdateReflectionInput): Promise<Task>;
79
+ /**
80
+ * Batch update all reflections belonging to a mission
81
+ */
82
+ batchUpdateByMission(missionId: string, data: Omit<BatchUpdateReflectionsInput, "missionId">): Promise<{
83
+ success: boolean;
84
+ }>;
85
+ /**
86
+ * Delete a reflection by ID
87
+ */
88
+ delete(id: string): Promise<void>;
89
+ /**
90
+ * Get all comments for a reflection
91
+ */
92
+ getComments(reflectionId: string): Promise<ReflectionComment[]>;
93
+ /**
94
+ * Add a comment to a reflection
95
+ */
96
+ addComment(reflectionId: string, data: AddReflectionCommentInput): Promise<ReflectionComment>;
97
+ /**
98
+ * Update a reflection comment by comment ID
99
+ */
100
+ updateComment(commentId: string, content: string): Promise<ReflectionComment>;
101
+ /**
102
+ * Delete a single reflection comment by comment ID
103
+ */
104
+ deleteComment(commentId: string): Promise<void>;
105
+ /**
106
+ * Batch delete all comments for a reflection
107
+ */
108
+ deleteAllComments(reflectionId: string): Promise<{
109
+ success: boolean;
110
+ }>;
111
+ }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReflectionsApi = void 0;
4
+ class ReflectionsApi {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ /**
9
+ * Get all reflections of a student, grouped by mission
10
+ */
11
+ list(params) {
12
+ const query = new URLSearchParams();
13
+ if (params.studentId)
14
+ query.append("studentId", params.studentId);
15
+ if (params.roadmapId)
16
+ query.append("roadmapId", params.roadmapId);
17
+ if (params.status)
18
+ params.status.forEach((s) => query.append("status", s));
19
+ if (params.description)
20
+ query.append("description", params.description);
21
+ if (params.limit !== undefined)
22
+ query.append("limit", params.limit.toString());
23
+ if (params.start !== undefined)
24
+ query.append("start", params.start.toString());
25
+ if (params.perMissionLimit !== undefined)
26
+ query.append("perMissionLimit", params.perMissionLimit.toString());
27
+ return this.client.fetch(`/roadmap/reflections?${query.toString()}`);
28
+ }
29
+ /**
30
+ * Get all reflections by mission ID
31
+ */
32
+ getByMission(missionId) {
33
+ return this.client.fetch(`/roadmap/missions/${missionId}/reflections`);
34
+ }
35
+ /**
36
+ * Create a new reflection for a mission
37
+ */
38
+ create(missionId, data) {
39
+ return this.client.fetch(`/roadmap/missions/${missionId}/reflections`, {
40
+ method: "POST",
41
+ body: JSON.stringify(data),
42
+ });
43
+ }
44
+ /**
45
+ * Update an existing reflection by ID
46
+ */
47
+ update(id, data) {
48
+ return this.client.fetch(`/roadmap/reflections/${id}`, {
49
+ method: "PUT",
50
+ body: JSON.stringify(data),
51
+ });
52
+ }
53
+ /**
54
+ * Batch update all reflections belonging to a mission
55
+ */
56
+ batchUpdateByMission(missionId, data) {
57
+ return this.client.fetch(`/roadmap/missions/${missionId}/reflections/batch`, {
58
+ method: "PUT",
59
+ body: JSON.stringify(data),
60
+ });
61
+ }
62
+ /**
63
+ * Delete a reflection by ID
64
+ */
65
+ delete(id) {
66
+ return this.client.fetch(`/roadmap/reflections/${id}`, {
67
+ method: "DELETE",
68
+ });
69
+ }
70
+ /**
71
+ * Get all comments for a reflection
72
+ */
73
+ getComments(reflectionId) {
74
+ return this.client.fetch(`/roadmap/reflections/${reflectionId}/comments`);
75
+ }
76
+ /**
77
+ * Add a comment to a reflection
78
+ */
79
+ addComment(reflectionId, data) {
80
+ return this.client.fetch(`/roadmap/reflections/${reflectionId}/comments`, {
81
+ method: "POST",
82
+ body: JSON.stringify(data),
83
+ });
84
+ }
85
+ /**
86
+ * Update a reflection comment by comment ID
87
+ */
88
+ updateComment(commentId, content) {
89
+ return this.client.fetch(`/roadmap/reflections/comments/${commentId}`, {
90
+ method: "PUT",
91
+ body: JSON.stringify({ content }),
92
+ });
93
+ }
94
+ /**
95
+ * Delete a single reflection comment by comment ID
96
+ */
97
+ deleteComment(commentId) {
98
+ return this.client.fetch(`/roadmap/reflections/comments/${commentId}`, {
99
+ method: "DELETE",
100
+ });
101
+ }
102
+ /**
103
+ * Batch delete all comments for a reflection
104
+ */
105
+ deleteAllComments(reflectionId) {
106
+ return this.client.fetch(`/roadmap/reflections/${reflectionId}/comments`, {
107
+ method: "DELETE",
108
+ });
109
+ }
110
+ }
111
+ exports.ReflectionsApi = ReflectionsApi;
@@ -39,7 +39,7 @@ export declare class TasksApi {
39
39
  missionLinkIds?: string[];
40
40
  roadmapId?: string;
41
41
  userId?: string;
42
- }, filters?: TaskFilters): Promise<PaginatedResult<Task>> | Promise<Task[]>;
42
+ }, filters?: TaskFilters): Promise<Task[]> | Promise<PaginatedResult<Task>>;
43
43
  /**
44
44
  * List tasks with pagination (requires roadmapId, always returns paginated result)
45
45
  */
@@ -1,4 +1,5 @@
1
1
  import type { OAuthConfig, TokenStorage } from "./auth/types";
2
+ import type { ReflectionComment } from "./reflections";
2
3
  /**
3
4
  * OAuth-specific configuration for CrimsonClient
4
5
  */
@@ -108,9 +109,15 @@ export interface Task {
108
109
  mission?: {
109
110
  id: string;
110
111
  title: string;
112
+ status?: string;
111
113
  linkId?: string;
112
114
  };
113
115
  createdAt?: string;
116
+ /** comment summary attached to reflection-type tasks */
117
+ comments?: {
118
+ total: number;
119
+ latest?: ReflectionComment;
120
+ };
114
121
  }
115
122
  export interface Mission {
116
123
  id: string;
@@ -213,6 +220,8 @@ export interface TemplateMission {
213
220
  actionItemCount?: number;
214
221
  actionItems?: TemplateTask[];
215
222
  resources?: TemplateMissionResource[];
223
+ visibleSc?: boolean;
224
+ visibleRoadmap?: boolean;
216
225
  createdAt?: string;
217
226
  updatedAt?: string;
218
227
  }
@@ -236,6 +245,8 @@ export interface MissionDetail {
236
245
  members?: string[];
237
246
  integrationSource?: string;
238
247
  attr?: string;
248
+ visibleSc?: boolean;
249
+ visibleRoadmap?: boolean;
239
250
  actionItems?: Array<{
240
251
  id: string;
241
252
  description: string;
@@ -249,6 +260,8 @@ export interface MissionDetail {
249
260
  taskGroup?: string;
250
261
  attr?: string;
251
262
  resources?: TemplateTaskResource[];
263
+ visibleSc?: boolean;
264
+ visibleRoadmap?: boolean;
252
265
  }>;
253
266
  resources?: TemplateMissionResource[];
254
267
  }
@@ -11,3 +11,4 @@ export { useTemplateMissions, useTemplateMissionsInfinite, useTemplateTasks, use
11
11
  export { useStudentProfile, useStudentPrefilledInfo, studentProfileKeys, } from "./useStudentProfile";
12
12
  export { useIndigoMe, useStudentTutors, useTutorStudents, indigoKeys, } from "./useIndigo";
13
13
  export * from "./useGradeTemplates";
14
+ export * from "./useReflections";
@@ -82,3 +82,4 @@ Object.defineProperty(exports, "useStudentTutors", { enumerable: true, get: func
82
82
  Object.defineProperty(exports, "useTutorStudents", { enumerable: true, get: function () { return useIndigo_1.useTutorStudents; } });
83
83
  Object.defineProperty(exports, "indigoKeys", { enumerable: true, get: function () { return useIndigo_1.indigoKeys; } });
84
84
  __exportStar(require("./useGradeTemplates"), exports);
85
+ __exportStar(require("./useReflections"), exports);
@@ -1,10 +1,11 @@
1
1
  import type { GradeTemplateFilters, CreateGradeTemplateInput, CreateGradeTemplateMissionInput, AddGradeTemplateToRoadmapInput } from "../../core/gradeTemplates";
2
+ export type { GradeTemplateFilters } from "../../core/gradeTemplates";
2
3
  export declare const gradeTemplateKeys: {
3
4
  all: readonly ["gradeTemplates"];
4
5
  list: (filters?: GradeTemplateFilters) => readonly ["gradeTemplates", "list", GradeTemplateFilters | undefined];
5
6
  detail: (id: string) => readonly ["gradeTemplates", "detail", string];
6
7
  };
7
- export declare function useGradeTemplates(filters?: GradeTemplateFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/gradeTemplates").GradeTemplate[], Error>;
8
+ export declare function useGradeTemplates(filters?: GradeTemplateFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/gradeTemplates").GradeTemplateBrief[], Error>;
8
9
  export declare function useGradeTemplate(id: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/gradeTemplates").GradeTemplate, Error>;
9
10
  export declare function useCreateGradeTemplate(): import("@tanstack/react-query").UseMutationResult<import("../../core/gradeTemplates").GradeTemplate, Error, CreateGradeTemplateInput, unknown>;
10
11
  export declare function useDeleteGradeTemplate(): import("@tanstack/react-query").UseMutationResult<void, Error, string, unknown>;
@@ -16,9 +17,7 @@ export declare function useRemoveMissionFromGradeTemplate(): import("@tanstack/r
16
17
  gradeTemplateId: string;
17
18
  missionId: string;
18
19
  }, unknown>;
19
- export declare function useAddGradeTemplateToRoadmap(): import("@tanstack/react-query").UseMutationResult<{
20
- success: boolean;
21
- }, Error, {
20
+ export declare function useAddGradeTemplateToRoadmap(): import("@tanstack/react-query").UseMutationResult<import("../../core/gradeTemplates").AddGradeTemplateToRoadmapResponse, Error, {
22
21
  id: string;
23
22
  input: AddGradeTemplateToRoadmapInput;
24
23
  }, unknown>;
@@ -43,7 +43,7 @@ function useCreateGradeTemplate() {
43
43
  mutationFn: (input) => client.gradeTemplates.createGradeTemplate(input),
44
44
  onSuccess: () => {
45
45
  queryClient.invalidateQueries({
46
- queryKey: exports.gradeTemplateKeys.list(),
46
+ queryKey: exports.gradeTemplateKeys.all,
47
47
  });
48
48
  },
49
49
  });
@@ -55,7 +55,7 @@ function useDeleteGradeTemplate() {
55
55
  mutationFn: (id) => client.gradeTemplates.deleteGradeTemplate(id),
56
56
  onSuccess: () => {
57
57
  queryClient.invalidateQueries({
58
- queryKey: exports.gradeTemplateKeys.list(),
58
+ queryKey: exports.gradeTemplateKeys.all,
59
59
  });
60
60
  },
61
61
  });
@@ -3,9 +3,9 @@ import type { TemplateMissionFilters, TemplateTaskFilters, CopyTemplateMissionIn
3
3
  export declare const missionLibraryKeys: {
4
4
  all: readonly ["missionLibrary"];
5
5
  missions: (filters?: TemplateMissionFilters) => readonly ["missionLibrary", "missions", TemplateMissionFilters | undefined];
6
- missionsInfinite: (filters?: Omit<TemplateMissionFilters, "start" | "limit">) => readonly ["missionLibrary", "missions", "infinite", Omit<TemplateMissionFilters, "start" | "limit"> | undefined];
6
+ missionsInfinite: (filters?: Omit<TemplateMissionFilters, "start" | "limit">) => readonly ["missionLibrary", "missions", "infinite", Omit<TemplateMissionFilters, "limit" | "start"> | undefined];
7
7
  tasks: (filters?: TemplateTaskFilters) => readonly ["missionLibrary", "tasks", TemplateTaskFilters | undefined];
8
- tasksInfinite: (filters?: Omit<TemplateTaskFilters, "start" | "limit">) => readonly ["missionLibrary", "tasks", "infinite", Omit<TemplateTaskFilters, "start" | "limit"> | undefined];
8
+ tasksInfinite: (filters?: Omit<TemplateTaskFilters, "start" | "limit">) => readonly ["missionLibrary", "tasks", "infinite", Omit<TemplateTaskFilters, "limit" | "start"> | undefined];
9
9
  missionDetail: (id: string) => readonly ["missionLibrary", "mission", string];
10
10
  };
11
11
  export declare function useTemplateMissions(filters?: TemplateMissionFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/types").PaginatedResult<TemplateMission>, Error>;
@@ -43,8 +43,4 @@ export declare function useAssignBulkTask(): import("@tanstack/react-query").Use
43
43
  msg?: string;
44
44
  }, Error, AssignBulkTaskInput[], unknown>;
45
45
  export declare function useCreateFromPredefinedTasks(): import("@tanstack/react-query").UseMutationResult<TemplateTask[], Error, CreateFromPredefinedInput, unknown>;
46
- export declare function useTemplateMissionAddToRoadmap(): import("@tanstack/react-query").UseMutationResult<{
47
- missionId: string;
48
- isNew: boolean;
49
- updated: boolean;
50
- }, Error, import("../../core/missionLibrary").AddTemplateMissionToRoadmapInput, unknown>;
46
+ export declare function useTemplateMissionAddToRoadmap(): import("@tanstack/react-query").UseMutationResult<import("../../core/missionLibrary").AddTemplateMissionToRoadmapResponse, Error, import("../../core/missionLibrary").AddTemplateMissionToRoadmapInput, unknown>;
@@ -5,7 +5,7 @@ export declare const missionKeys: {
5
5
  all: readonly ["missions"];
6
6
  lists: () => readonly ["missions", "list"];
7
7
  list: (userId: string) => readonly ["missions", "list", string];
8
- infinite: (userId: string, filters?: Omit<MissionFilters, "start" | "limit">) => readonly ["missions", "infinite", string, Omit<MissionFilters, "start" | "limit"> | undefined];
8
+ infinite: (userId: string, filters?: Omit<MissionFilters, "start" | "limit">) => readonly ["missions", "infinite", string, Omit<MissionFilters, "limit" | "start"> | undefined];
9
9
  details: () => readonly ["missions", "detail"];
10
10
  detail: (id: string) => readonly ["missions", "detail", string];
11
11
  };
@@ -0,0 +1,101 @@
1
+ import { type UseQueryOptions, type UseMutationOptions } from "@tanstack/react-query";
2
+ import type { Task } from "../../core/types";
3
+ import type { CreateReflectionInput, UpdateReflectionInput, BatchUpdateReflectionsInput, ListReflectionsResponse, ReflectionComment, AddReflectionCommentInput } from "../../core/reflections";
4
+ export declare const REFLECTION_KEYS: {
5
+ all: readonly ["reflections"];
6
+ list: (params: {
7
+ studentId: string;
8
+ roadmapId?: string;
9
+ status?: string[];
10
+ description?: string;
11
+ limit?: number;
12
+ start?: number;
13
+ perMissionLimit?: number;
14
+ }) => readonly ["reflections", "list", {
15
+ studentId: string;
16
+ roadmapId?: string;
17
+ status?: string[];
18
+ description?: string;
19
+ limit?: number;
20
+ start?: number;
21
+ perMissionLimit?: number;
22
+ }];
23
+ byMission: (missionId: string) => readonly ["reflections", "mission", string];
24
+ comments: (reflectionId: string) => readonly ["reflections", "comments", string];
25
+ };
26
+ export declare function useAllReflections(params: {
27
+ studentId: string;
28
+ roadmapId?: string;
29
+ status?: string[];
30
+ description?: string;
31
+ limit?: number;
32
+ start?: number;
33
+ perMissionLimit?: number;
34
+ }, options?: Omit<UseQueryOptions<ListReflectionsResponse, Error, ListReflectionsResponse, readonly any[]>, "queryKey" | "queryFn">): import("@tanstack/react-query").UseQueryResult<ListReflectionsResponse, Error>;
35
+ export declare function useReflections(missionId: string, options?: Omit<UseQueryOptions<Task[], Error, Task[], readonly string[]>, "queryKey" | "queryFn">): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
36
+ export declare function useCreateReflection(options?: Omit<UseMutationOptions<Task, Error, CreateReflectionInput>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<Task, Error, CreateReflectionInput, unknown>;
37
+ export declare function useUpdateReflection(options?: Omit<UseMutationOptions<Task, Error, {
38
+ id: string;
39
+ missionId: string;
40
+ } & UpdateReflectionInput>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<Task, Error, {
41
+ id: string;
42
+ missionId: string;
43
+ } & UpdateReflectionInput, any>;
44
+ export declare function useBatchUpdateReflections(options?: Omit<UseMutationOptions<{
45
+ success: boolean;
46
+ }, Error, BatchUpdateReflectionsInput>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<{
47
+ success: boolean;
48
+ }, Error, BatchUpdateReflectionsInput, unknown>;
49
+ export declare function useDeleteReflection(options?: Omit<UseMutationOptions<void, Error, {
50
+ id: string;
51
+ missionId: string;
52
+ }>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<void, Error, {
53
+ id: string;
54
+ missionId: string;
55
+ }, unknown>;
56
+ /**
57
+ * Fetch all comments for a reflection (action item)
58
+ */
59
+ export declare function useReflectionComments(reflectionId: string, options?: Omit<UseQueryOptions<ReflectionComment[], Error, ReflectionComment[], readonly string[]>, "queryKey" | "queryFn">): import("@tanstack/react-query").UseQueryResult<ReflectionComment[], Error>;
60
+ /**
61
+ * Add a comment to a reflection
62
+ */
63
+ export declare function useAddReflectionComment(options?: Omit<UseMutationOptions<ReflectionComment, Error, {
64
+ reflectionId: string;
65
+ } & AddReflectionCommentInput>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<ReflectionComment, Error, {
66
+ reflectionId: string;
67
+ } & AddReflectionCommentInput, any>;
68
+ /**
69
+ * Update a reflection comment
70
+ */
71
+ export declare function useUpdateReflectionComment(options?: Omit<UseMutationOptions<ReflectionComment, Error, {
72
+ commentId: string;
73
+ reflectionId: string;
74
+ content: string;
75
+ }>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<ReflectionComment, Error, {
76
+ commentId: string;
77
+ reflectionId: string;
78
+ content: string;
79
+ }, unknown>;
80
+ /**
81
+ * Delete a single reflection comment
82
+ */
83
+ export declare function useDeleteReflectionComment(options?: Omit<UseMutationOptions<void, Error, {
84
+ commentId: string;
85
+ reflectionId: string;
86
+ }>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<void, Error, {
87
+ commentId: string;
88
+ reflectionId: string;
89
+ }, unknown>;
90
+ /**
91
+ * Batch delete all comments for a reflection
92
+ */
93
+ export declare function useDeleteAllReflectionComments(options?: Omit<UseMutationOptions<{
94
+ success: boolean;
95
+ }, Error, {
96
+ reflectionId: string;
97
+ }>, "mutationFn">): import("@tanstack/react-query").UseMutationResult<{
98
+ success: boolean;
99
+ }, Error, {
100
+ reflectionId: string;
101
+ }, unknown>;
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.REFLECTION_KEYS = void 0;
24
+ exports.useAllReflections = useAllReflections;
25
+ exports.useReflections = useReflections;
26
+ exports.useCreateReflection = useCreateReflection;
27
+ exports.useUpdateReflection = useUpdateReflection;
28
+ exports.useBatchUpdateReflections = useBatchUpdateReflections;
29
+ exports.useDeleteReflection = useDeleteReflection;
30
+ exports.useReflectionComments = useReflectionComments;
31
+ exports.useAddReflectionComment = useAddReflectionComment;
32
+ exports.useUpdateReflectionComment = useUpdateReflectionComment;
33
+ exports.useDeleteReflectionComment = useDeleteReflectionComment;
34
+ exports.useDeleteAllReflectionComments = useDeleteAllReflectionComments;
35
+ const react_query_1 = require("@tanstack/react-query");
36
+ const provider_1 = require("../provider");
37
+ exports.REFLECTION_KEYS = {
38
+ all: ["reflections"],
39
+ list: (params) => [...exports.REFLECTION_KEYS.all, "list", params],
40
+ byMission: (missionId) => [...exports.REFLECTION_KEYS.all, "mission", missionId],
41
+ comments: (reflectionId) => [...exports.REFLECTION_KEYS.all, "comments", reflectionId],
42
+ };
43
+ function useAllReflections(params, options) {
44
+ const client = (0, provider_1.useCrimsonClient)();
45
+ return (0, react_query_1.useQuery)(Object.assign({ queryKey: exports.REFLECTION_KEYS.list(params), queryFn: () => client.reflections.list(params), enabled: !!client && !!params.studentId && (options === null || options === void 0 ? void 0 : options.enabled) !== false }, options));
46
+ }
47
+ function useReflections(missionId, options) {
48
+ const client = (0, provider_1.useCrimsonClient)();
49
+ return (0, react_query_1.useQuery)(Object.assign({ queryKey: exports.REFLECTION_KEYS.byMission(missionId), queryFn: () => client.reflections.getByMission(missionId), enabled: !!client && !!missionId && (options === null || options === void 0 ? void 0 : options.enabled) !== false }, options));
50
+ }
51
+ function useCreateReflection(options) {
52
+ const client = (0, provider_1.useCrimsonClient)();
53
+ const queryClient = (0, react_query_1.useQueryClient)();
54
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: (data) => {
55
+ const { missionId } = data, rest = __rest(data, ["missionId"]);
56
+ return client.reflections.create(missionId, rest);
57
+ }, onSuccess: (data, variables, context) => {
58
+ queryClient.invalidateQueries({
59
+ queryKey: [...exports.REFLECTION_KEYS.all, "list"],
60
+ });
61
+ queryClient.invalidateQueries({
62
+ queryKey: exports.REFLECTION_KEYS.byMission(variables.missionId),
63
+ });
64
+ if (options === null || options === void 0 ? void 0 : options.onSuccess) {
65
+ options.onSuccess(data, variables, context, context);
66
+ }
67
+ } }, options));
68
+ }
69
+ function useUpdateReflection(options) {
70
+ const client = (0, provider_1.useCrimsonClient)();
71
+ const queryClient = (0, react_query_1.useQueryClient)();
72
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: (_a) => {
73
+ var { id } = _a, data = __rest(_a, ["id"]);
74
+ return client.reflections.update(id, data);
75
+ }, onMutate: (variables) => __awaiter(this, void 0, void 0, function* () {
76
+ // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
77
+ yield queryClient.cancelQueries({ queryKey: exports.REFLECTION_KEYS.all });
78
+ const previousReflectionsMap = new Map();
79
+ // Snapshot the previous value
80
+ queryClient
81
+ .getQueriesData({ queryKey: exports.REFLECTION_KEYS.all })
82
+ .forEach(([key, old]) => {
83
+ previousReflectionsMap.set(JSON.stringify(key), old);
84
+ if (!old)
85
+ return;
86
+ // Handle ListReflectionsResponse (list)
87
+ if (typeof old === "object" && "data" in old && Array.isArray(old.data)) {
88
+ queryClient.setQueryData(key, (oldData) => {
89
+ if (!oldData)
90
+ return oldData;
91
+ return Object.assign(Object.assign({}, oldData), { data: oldData.data.map((group) => (Object.assign(Object.assign({}, group), { reflections: group.reflections.map((reflection) => reflection.id === variables.id
92
+ ? Object.assign(Object.assign({}, reflection), variables) : reflection) }))) });
93
+ });
94
+ }
95
+ // Handle Task[] (byMission)
96
+ else if (Array.isArray(old)) {
97
+ queryClient.setQueryData(key, (oldData) => {
98
+ return oldData === null || oldData === void 0 ? void 0 : oldData.map((reflection) => reflection.id === variables.id
99
+ ? Object.assign(Object.assign({}, reflection), variables) : reflection);
100
+ });
101
+ }
102
+ });
103
+ return { previousReflectionsMap };
104
+ }), onError: (err, variables, context) => {
105
+ if (context === null || context === void 0 ? void 0 : context.previousReflectionsMap) {
106
+ context.previousReflectionsMap.forEach((old, keyStr) => {
107
+ queryClient.setQueryData(JSON.parse(keyStr), old);
108
+ });
109
+ }
110
+ }, onSettled: (_data, _error, variables) => {
111
+ queryClient.invalidateQueries({
112
+ queryKey: [...exports.REFLECTION_KEYS.all, "list"],
113
+ });
114
+ if (variables.missionId) {
115
+ queryClient.invalidateQueries({
116
+ queryKey: exports.REFLECTION_KEYS.byMission(variables.missionId),
117
+ });
118
+ }
119
+ } }, options));
120
+ }
121
+ function useBatchUpdateReflections(options) {
122
+ const client = (0, provider_1.useCrimsonClient)();
123
+ const queryClient = (0, react_query_1.useQueryClient)();
124
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: (data) => {
125
+ const { missionId } = data, rest = __rest(data, ["missionId"]);
126
+ return client.reflections.batchUpdateByMission(missionId, rest);
127
+ }, onSuccess: (data, variables, context) => {
128
+ queryClient.invalidateQueries({
129
+ queryKey: [...exports.REFLECTION_KEYS.all, "list"],
130
+ });
131
+ queryClient.invalidateQueries({
132
+ queryKey: exports.REFLECTION_KEYS.byMission(variables.missionId),
133
+ });
134
+ if (options === null || options === void 0 ? void 0 : options.onSuccess) {
135
+ options.onSuccess(data, variables, context, context);
136
+ }
137
+ } }, options));
138
+ }
139
+ function useDeleteReflection(options) {
140
+ const client = (0, provider_1.useCrimsonClient)();
141
+ const queryClient = (0, react_query_1.useQueryClient)();
142
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: ({ id }) => client.reflections.delete(id), onSuccess: (data, variables, context) => {
143
+ queryClient.invalidateQueries({
144
+ queryKey: [...exports.REFLECTION_KEYS.all, "list"],
145
+ });
146
+ queryClient.invalidateQueries({
147
+ queryKey: exports.REFLECTION_KEYS.byMission(variables.missionId),
148
+ });
149
+ if (options === null || options === void 0 ? void 0 : options.onSuccess) {
150
+ options.onSuccess(data, variables, context, context);
151
+ }
152
+ } }, options));
153
+ }
154
+ /**
155
+ * Fetch all comments for a reflection (action item)
156
+ */
157
+ function useReflectionComments(reflectionId, options) {
158
+ const client = (0, provider_1.useCrimsonClient)();
159
+ return (0, react_query_1.useQuery)(Object.assign({ queryKey: exports.REFLECTION_KEYS.comments(reflectionId), queryFn: () => client.reflections.getComments(reflectionId), enabled: !!client && !!reflectionId && (options === null || options === void 0 ? void 0 : options.enabled) !== false }, options));
160
+ }
161
+ /**
162
+ * Add a comment to a reflection
163
+ */
164
+ function useAddReflectionComment(options) {
165
+ const client = (0, provider_1.useCrimsonClient)();
166
+ const queryClient = (0, react_query_1.useQueryClient)();
167
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: (_a) => {
168
+ var { reflectionId } = _a, data = __rest(_a, ["reflectionId"]);
169
+ return client.reflections.addComment(reflectionId, data);
170
+ }, onMutate: (variables) => __awaiter(this, void 0, void 0, function* () {
171
+ // Cancel outgoing refetches
172
+ yield queryClient.cancelQueries({ queryKey: exports.REFLECTION_KEYS.all });
173
+ const previousReflectionsMap = new Map();
174
+ // Snapshot the previous values
175
+ queryClient
176
+ .getQueriesData({ queryKey: exports.REFLECTION_KEYS.all })
177
+ .forEach(([key, old]) => {
178
+ previousReflectionsMap.set(JSON.stringify(key), old);
179
+ if (!old)
180
+ return;
181
+ // Handle ReflectionComment[] (comments for specific reflection)
182
+ if (Array.isArray(old) && key.includes("comments") && key.includes(variables.reflectionId)) {
183
+ const optimisticComment = {
184
+ id: `temp-${Date.now()}`,
185
+ content: variables.content,
186
+ createdAt: new Date().toISOString(),
187
+ creatorName: "You", // placeholder, will be updated by server
188
+ };
189
+ queryClient.setQueryData(key, (oldData) => {
190
+ return oldData ? [...oldData, optimisticComment] : [optimisticComment];
191
+ });
192
+ }
193
+ // Handle ListReflectionsResponse (updating latest comment summary in the list)
194
+ else if (typeof old === "object" && "data" in old && Array.isArray(old.data)) {
195
+ queryClient.setQueryData(key, (oldData) => {
196
+ if (!oldData)
197
+ return oldData;
198
+ const optimisticComment = {
199
+ id: `temp-${Date.now()}`,
200
+ content: variables.content,
201
+ createdAt: new Date().toISOString(),
202
+ creatorName: "You",
203
+ };
204
+ return Object.assign(Object.assign({}, oldData), { data: oldData.data.map((group) => (Object.assign(Object.assign({}, group), { reflections: group.reflections.map((reflection) => {
205
+ var _a, _b;
206
+ if (reflection.id === variables.reflectionId) {
207
+ const currentTotal = (_b = (_a = reflection.comments) === null || _a === void 0 ? void 0 : _a.total) !== null && _b !== void 0 ? _b : 0;
208
+ return Object.assign(Object.assign({}, reflection), { comments: {
209
+ total: currentTotal + 1,
210
+ latest: optimisticComment,
211
+ } });
212
+ }
213
+ return reflection;
214
+ }) }))) });
215
+ });
216
+ }
217
+ });
218
+ return { previousReflectionsMap };
219
+ }), onError: (err, variables, context) => {
220
+ if (context === null || context === void 0 ? void 0 : context.previousReflectionsMap) {
221
+ context.previousReflectionsMap.forEach((old, keyStr) => {
222
+ queryClient.setQueryData(JSON.parse(keyStr), old);
223
+ });
224
+ }
225
+ }, onSettled: (_data, _error, variables) => {
226
+ queryClient.invalidateQueries({
227
+ queryKey: [...exports.REFLECTION_KEYS.all, "list"],
228
+ });
229
+ queryClient.invalidateQueries({
230
+ queryKey: exports.REFLECTION_KEYS.comments(variables.reflectionId),
231
+ });
232
+ } }, options));
233
+ }
234
+ /**
235
+ * Update a reflection comment
236
+ */
237
+ function useUpdateReflectionComment(options) {
238
+ const client = (0, provider_1.useCrimsonClient)();
239
+ const queryClient = (0, react_query_1.useQueryClient)();
240
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: ({ commentId, content }) => client.reflections.updateComment(commentId, content), onSuccess: (data, variables, context) => {
241
+ queryClient.invalidateQueries({
242
+ queryKey: exports.REFLECTION_KEYS.comments(variables.reflectionId),
243
+ });
244
+ if (options === null || options === void 0 ? void 0 : options.onSuccess) {
245
+ options.onSuccess(data, variables, context, context);
246
+ }
247
+ } }, options));
248
+ }
249
+ /**
250
+ * Delete a single reflection comment
251
+ */
252
+ function useDeleteReflectionComment(options) {
253
+ const client = (0, provider_1.useCrimsonClient)();
254
+ const queryClient = (0, react_query_1.useQueryClient)();
255
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: ({ commentId }) => client.reflections.deleteComment(commentId), onSuccess: (data, variables, context) => {
256
+ queryClient.invalidateQueries({
257
+ queryKey: exports.REFLECTION_KEYS.comments(variables.reflectionId),
258
+ });
259
+ if (options === null || options === void 0 ? void 0 : options.onSuccess) {
260
+ options.onSuccess(data, variables, context, context);
261
+ }
262
+ } }, options));
263
+ }
264
+ /**
265
+ * Batch delete all comments for a reflection
266
+ */
267
+ function useDeleteAllReflectionComments(options) {
268
+ const client = (0, provider_1.useCrimsonClient)();
269
+ const queryClient = (0, react_query_1.useQueryClient)();
270
+ return (0, react_query_1.useMutation)(Object.assign({ mutationFn: ({ reflectionId }) => client.reflections.deleteAllComments(reflectionId), onSuccess: (data, variables, context) => {
271
+ queryClient.invalidateQueries({
272
+ queryKey: exports.REFLECTION_KEYS.comments(variables.reflectionId),
273
+ });
274
+ if (options === null || options === void 0 ? void 0 : options.onSuccess) {
275
+ options.onSuccess(data, variables, context, context);
276
+ }
277
+ } }, options));
278
+ }
@@ -5,7 +5,7 @@ export declare const taskKeys: {
5
5
  all: readonly ["tasks"];
6
6
  lists: () => readonly ["tasks", "list"];
7
7
  list: (missionId: string) => readonly ["tasks", "list", string];
8
- infinite: (roadmapId: string, userId: string, filters?: Omit<TaskFilters, "start" | "limit">) => readonly ["tasks", "infinite", string, string, Omit<TaskFilters, "start" | "limit"> | undefined];
8
+ infinite: (roadmapId: string, userId: string, filters?: Omit<TaskFilters, "start" | "limit">) => readonly ["tasks", "infinite", string, string, Omit<TaskFilters, "limit" | "start"> | undefined];
9
9
  details: () => readonly ["tasks", "detail"];
10
10
  detail: (id: string) => readonly ["tasks", "detail", string];
11
11
  creators: (roadmapId: string) => readonly ["tasks", "creators", string];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crimson-education/sdk",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
4
4
  "description": "Crimson SDK for accessing Crimson App APIs",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",