@crimson-education/sdk 0.3.12 → 0.3.14

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,7 +1,6 @@
1
1
  import type { CrimsonClientConfig } from "./types";
2
2
  import { MissionsApi } from "./missions";
3
3
  import { TasksApi } from "./tasks";
4
- import { ReflectionsApi } from "./reflections";
5
4
  import { RoadmapApi } from "./roadmap";
6
5
  import { MissionLibraryApi } from "./missionLibrary";
7
6
  import { UsersApi } from "./users";
@@ -106,7 +105,6 @@ export declare class CrimsonClient {
106
105
  destroy(): void;
107
106
  missions: MissionsApi;
108
107
  tasks: TasksApi;
109
- reflections: ReflectionsApi;
110
108
  roadmap: RoadmapApi;
111
109
  library: MissionLibraryApi;
112
110
  users: UsersApi;
@@ -13,7 +13,6 @@ 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");
17
16
  const roadmap_1 = require("./roadmap");
18
17
  const missionLibrary_1 = require("./missionLibrary");
19
18
  const users_1 = require("./users");
@@ -49,7 +48,6 @@ class CrimsonClient {
49
48
  this.isResolvingDomain = false;
50
49
  this.missions = new missions_1.MissionsApi(this);
51
50
  this.tasks = new tasks_1.TasksApi(this);
52
- this.reflections = new reflections_1.ReflectionsApi(this);
53
51
  this.roadmap = new roadmap_1.RoadmapApi(this);
54
52
  this.library = new missionLibrary_1.MissionLibraryApi(this);
55
53
  this.users = new users_1.UsersApi(this);
@@ -1,18 +1,14 @@
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";
5
2
  export interface GradeTemplateMission {
6
3
  id: string;
7
4
  gradeTemplateId: string;
8
5
  templateMissionId: string;
9
6
  startYearOffset?: number;
10
- startMonth?: number | null;
7
+ startMonth: number;
11
8
  startDay?: number;
12
9
  endYearOffset?: number;
13
- endMonth?: number | null;
10
+ endMonth: number;
14
11
  endDay?: number;
15
- orderIndex?: number;
16
12
  createdAt: string;
17
13
  updatedAt: string;
18
14
  title?: string;
@@ -37,30 +33,23 @@ export interface GradeTemplateTask {
37
33
  }
38
34
  export interface CreateGradeTemplateMissionInput {
39
35
  templateMissionId: string;
40
- tenantId?: string;
41
36
  startYearOffset?: number;
42
- startMonth?: number | null;
37
+ startMonth: number;
43
38
  startDay?: number;
44
39
  endYearOffset?: number;
45
- endMonth?: number | null;
40
+ endMonth: number;
46
41
  endDay?: number;
47
- orderIndex?: number;
48
42
  }
49
43
  export interface GradeTemplateBrief {
50
44
  id: string;
51
45
  title: string;
52
- type?: GradeTemplateType;
53
- division?: GradeTemplateDivision[] | null;
54
- creatorId?: string;
55
- group?: GradeTemplateGroup;
56
- gradeLevel?: number | null;
46
+ gradeLevel: number;
57
47
  startYearOffset?: number;
58
- startMonth?: number | null;
48
+ startMonth: number;
59
49
  startDay?: number;
60
50
  endYearOffset?: number;
61
- endMonth?: number | null;
51
+ endMonth: number;
62
52
  endDay?: number;
63
- numMissions?: number;
64
53
  }
65
54
  export interface GradeTemplate extends GradeTemplateBrief {
66
55
  missions: GradeTemplateMission[];
@@ -69,27 +58,18 @@ export interface GradeTemplate extends GradeTemplateBrief {
69
58
  }
70
59
  export interface CreateGradeTemplateInput {
71
60
  title: string;
72
- tenantId?: string;
73
- type?: GradeTemplateType;
74
- division?: GradeTemplateDivision[] | null;
75
- creatorId?: string;
76
- group?: GradeTemplateGroup;
77
- gradeLevel?: number | null;
61
+ gradeLevel: number;
78
62
  startYearOffset?: number;
79
- startMonth?: number | null;
63
+ startMonth: number;
80
64
  startDay?: number;
81
65
  endYearOffset?: number;
82
- endMonth?: number | null;
66
+ endMonth: number;
83
67
  endDay?: number;
84
68
  }
85
69
  export interface GradeTemplateFilters {
86
70
  ids?: string[];
87
71
  startGrade?: number;
88
72
  endGrade?: number;
89
- groups?: GradeTemplateGroup[];
90
- type?: GradeTemplateType;
91
- division?: GradeTemplateDivision[];
92
- numMissions?: boolean;
93
73
  }
94
74
  export interface AddGradeTemplateToRoadmapInput {
95
75
  studentId: string;
@@ -115,7 +95,7 @@ export declare class GradeTemplatesApi {
115
95
  /**
116
96
  * List grade templates
117
97
  */
118
- listGradeTemplates(filters?: GradeTemplateFilters): Promise<GradeTemplateBrief[]>;
98
+ listGradeTemplates(filters?: GradeTemplateFilters): Promise<GradeTemplate[]>;
119
99
  /**
120
100
  * Get grade template by ID
121
101
  */
@@ -19,7 +19,6 @@ class GradeTemplatesApi {
19
19
  */
20
20
  listGradeTemplates(filters) {
21
21
  return __awaiter(this, void 0, void 0, function* () {
22
- var _a, _b;
23
22
  const params = new URLSearchParams();
24
23
  if ((filters === null || filters === void 0 ? void 0 : filters.startGrade) !== undefined) {
25
24
  params.append("startgrade", String(filters.startGrade));
@@ -27,18 +26,6 @@ class GradeTemplatesApi {
27
26
  if ((filters === null || filters === void 0 ? void 0 : filters.endGrade) !== undefined) {
28
27
  params.append("endgrade", String(filters.endGrade));
29
28
  }
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
- }
42
29
  const query = params.toString();
43
30
  const path = query
44
31
  ? `/roadmap/grade-templates?${query}`
@@ -1,7 +1,6 @@
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";
5
4
  export { RoadmapApi } from "./roadmap";
6
5
  export { MissionLibraryApi } from "./missionLibrary";
7
6
  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.ReflectionsApi = 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.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,8 +22,6 @@ 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; } });
27
25
  var roadmap_1 = require("./roadmap");
28
26
  Object.defineProperty(exports, "RoadmapApi", { enumerable: true, get: function () { return roadmap_1.RoadmapApi; } });
29
27
  var missionLibrary_1 = require("./missionLibrary");
@@ -6,8 +6,6 @@ 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>;
11
9
  }
12
10
  export interface TemplateTaskFilters extends PaginationParams {
13
11
  categories?: string[];
@@ -22,15 +20,11 @@ export interface TemplateTaskUpdateInput {
22
20
  title?: string;
23
21
  description?: string;
24
22
  operation: string;
25
- visibleSc?: boolean;
26
- visibleRoadmap?: boolean;
27
23
  }
28
24
  export interface TemplateMissionUpdateInput {
29
25
  title?: string;
30
26
  description?: string;
31
27
  tasks?: TemplateTaskUpdateInput[];
32
- visibleSc?: boolean;
33
- visibleRoadmap?: boolean;
34
28
  }
35
29
  export interface CopyTemplateMissionInput {
36
30
  linkId: string;
@@ -50,14 +44,10 @@ export interface TemplateMissionCreateInput {
50
44
  description: string;
51
45
  category: string;
52
46
  subcategory: string;
53
- visibleSc?: boolean;
54
- visibleRoadmap?: boolean;
55
47
  tasks: {
56
48
  id?: string | null;
57
49
  description: string;
58
50
  content: string;
59
- visibleSc?: boolean;
60
- visibleRoadmap?: boolean;
61
51
  }[];
62
52
  }
63
53
  export interface AddTemplateMissionToRoadmapInput {
@@ -36,12 +36,6 @@ 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
- }
45
39
  if ((filters === null || filters === void 0 ? void 0 : filters.start) !== undefined) {
46
40
  params.append("start", String(filters.start));
47
41
  }
@@ -173,13 +167,11 @@ class MissionLibraryApi {
173
167
  */
174
168
  updateTemplateMission(id, raw, update) {
175
169
  return __awaiter(this, void 0, void 0, function* () {
176
- var _a, _b, _c, _d;
170
+ var _a, _b;
177
171
  const data = {
178
172
  title: (_a = update.title) !== null && _a !== void 0 ? _a : raw.title,
179
173
  description: (_b = update.description) !== null && _b !== void 0 ? _b : raw.description,
180
174
  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,
183
175
  // only allow updatecustom
184
176
  type: 'custom',
185
177
  category: raw.category,
@@ -7,6 +7,8 @@ export interface MissionFilters extends PaginationParams {
7
7
  groupBy?: string;
8
8
  dueDateStart?: string;
9
9
  dueDateEnd?: string;
10
+ visibleSc?: boolean;
11
+ visibleRoadmap?: boolean;
10
12
  }
11
13
  export declare class MissionsApi {
12
14
  private client;
@@ -22,7 +24,10 @@ export declare class MissionsApi {
22
24
  * Handles both new paginated response and legacy category-grouped response
23
25
  */
24
26
  listPaginated(userId: string, filters?: Omit<MissionFilters, "start" | "limit">, pagination?: PaginationParams): Promise<PaginatedResult<Mission>>;
25
- create(data: Partial<Mission>): Promise<Mission>;
27
+ create(data: Partial<Mission> & {
28
+ visibleSc?: boolean;
29
+ visibleRoadmap?: boolean;
30
+ }): Promise<Mission>;
26
31
  update(linkId: string, data: Partial<Mission>): Promise<Mission>;
27
32
  delete(linkId: string): Promise<void>;
28
33
  /**
@@ -31,7 +36,7 @@ export declare class MissionsApi {
31
36
  * @param roadmapId - The roadmap ID
32
37
  * @param missions - Array of mission operations
33
38
  */
34
- batchEdit(userId: string, roadmapId: string, missions: BatchMissionOperation[]): Promise<BatchEditMissionsResult[]>;
39
+ batchEdit(userId: string, roadmapId: string, missions: BatchMissionOperation[], visibleSc?: boolean, visibleRoadmap?: boolean): Promise<BatchEditMissionsResult[]>;
35
40
  /**
36
41
  * Batch delete missions and their action items by link IDs
37
42
  * @param linkIds - Array of mission link IDs to delete
@@ -40,6 +40,12 @@ class MissionsApi {
40
40
  if (filters === null || filters === void 0 ? void 0 : filters.dueDateEnd) {
41
41
  params.append("dueDateEnd", filters.dueDateEnd);
42
42
  }
43
+ if ((filters === null || filters === void 0 ? void 0 : filters.visibleSc) !== undefined) {
44
+ params.append("visibleSc", String(filters.visibleSc));
45
+ }
46
+ if ((filters === null || filters === void 0 ? void 0 : filters.visibleRoadmap) !== undefined) {
47
+ params.append("visibleRoadmap", String(filters.visibleRoadmap));
48
+ }
43
49
  if ((filters === null || filters === void 0 ? void 0 : filters.start) !== undefined) {
44
50
  params.append("start", String(filters.start));
45
51
  }
@@ -110,10 +116,16 @@ class MissionsApi {
110
116
  * @param roadmapId - The roadmap ID
111
117
  * @param missions - Array of mission operations
112
118
  */
113
- batchEdit(userId, roadmapId, missions) {
119
+ batchEdit(userId, roadmapId, missions, visibleSc, visibleRoadmap) {
114
120
  return this.client.fetch("/roadmap/missions/batch", {
115
121
  method: "POST",
116
- body: JSON.stringify({ userId, roadmapId, missions }),
122
+ body: JSON.stringify({
123
+ userId,
124
+ roadmapId,
125
+ missions,
126
+ visibleSc,
127
+ visibleRoadmap,
128
+ }),
117
129
  });
118
130
  }
119
131
  /**
@@ -23,6 +23,8 @@ export interface TaskFilters extends PaginationParams {
23
23
  creatorId?: string;
24
24
  dueDateStart?: string;
25
25
  dueDateEnd?: string;
26
+ visibleSc?: boolean;
27
+ visibleRoadmap?: boolean;
26
28
  orderBy?: TaskOrderBy;
27
29
  order?: "asc" | "desc";
28
30
  }
@@ -39,11 +41,14 @@ export declare class TasksApi {
39
41
  missionLinkIds?: string[];
40
42
  roadmapId?: string;
41
43
  userId?: string;
42
- }, filters?: TaskFilters): Promise<Task[]> | Promise<PaginatedResult<Task>>;
44
+ }, filters?: TaskFilters): Promise<PaginatedResult<Task>> | Promise<Task[]>;
43
45
  /**
44
46
  * List tasks with pagination (requires roadmapId, always returns paginated result)
45
47
  */
46
- listPaginated(roadmapId: string, userId: string, filters?: Omit<TaskFilters, "start" | "limit">, pagination?: PaginationParams): Promise<PaginatedResult<Task>>;
48
+ listPaginated(roadmapId: string, userId: string, filters: Omit<TaskFilters, "start" | "limit"> & {
49
+ visibleSc?: boolean;
50
+ visibleRoadmap?: boolean;
51
+ }, pagination?: PaginationParams): Promise<PaginatedResult<Task>>;
47
52
  /**
48
53
  * Get all creators of tasks in a roadmap
49
54
  */
@@ -22,11 +22,9 @@ const normalizeTask = (raw) => {
22
22
  throw new Error("Task object missing required 'id' field");
23
23
  }
24
24
  const statusUpper = typeof raw.status === "string" ? raw.status.toUpperCase() : undefined;
25
- const isComplete = raw.isComplete !== undefined
26
- ? Boolean(raw.isComplete)
27
- : statusUpper
28
- ? statusUpper === "DONE"
29
- : Boolean(raw.finishedAt);
25
+ // Use status as the source of truth for completion.
26
+ // Keep isComplete for backward compatibility with existing consumers.
27
+ const isComplete = statusUpper === "DONE";
30
28
  return {
31
29
  id: (_a = raw.id) !== null && _a !== void 0 ? _a : "",
32
30
  name: (_c = (_b = raw.name) !== null && _b !== void 0 ? _b : raw.description) !== null && _c !== void 0 ? _c : "",
@@ -85,6 +83,12 @@ class TasksApi {
85
83
  if (filters === null || filters === void 0 ? void 0 : filters.dueDateEnd) {
86
84
  searchParams.append("dueDateEnd", filters.dueDateEnd);
87
85
  }
86
+ if ((filters === null || filters === void 0 ? void 0 : filters.visibleSc) !== undefined) {
87
+ searchParams.append("visibleSc", String(filters.visibleSc));
88
+ }
89
+ if ((filters === null || filters === void 0 ? void 0 : filters.visibleRoadmap) !== undefined) {
90
+ searchParams.append("visibleRoadmap", String(filters.visibleRoadmap));
91
+ }
88
92
  if (filters === null || filters === void 0 ? void 0 : filters.orderBy) {
89
93
  searchParams.append("orderBy", filters.orderBy);
90
94
  }
@@ -1,5 +1,4 @@
1
1
  import type { OAuthConfig, TokenStorage } from "./auth/types";
2
- import type { ReflectionComment } from "./reflections";
3
2
  /**
4
3
  * OAuth-specific configuration for CrimsonClient
5
4
  */
@@ -109,15 +108,9 @@ export interface Task {
109
108
  mission?: {
110
109
  id: string;
111
110
  title: string;
112
- status?: string;
113
111
  linkId?: string;
114
112
  };
115
113
  createdAt?: string;
116
- /** comment summary attached to reflection-type tasks */
117
- comments?: {
118
- total: number;
119
- latest?: ReflectionComment;
120
- };
121
114
  }
122
115
  export interface Mission {
123
116
  id: string;
@@ -220,8 +213,6 @@ export interface TemplateMission {
220
213
  actionItemCount?: number;
221
214
  actionItems?: TemplateTask[];
222
215
  resources?: TemplateMissionResource[];
223
- visibleSc?: boolean;
224
- visibleRoadmap?: boolean;
225
216
  createdAt?: string;
226
217
  updatedAt?: string;
227
218
  }
@@ -245,8 +236,6 @@ export interface MissionDetail {
245
236
  members?: string[];
246
237
  integrationSource?: string;
247
238
  attr?: string;
248
- visibleSc?: boolean;
249
- visibleRoadmap?: boolean;
250
239
  actionItems?: Array<{
251
240
  id: string;
252
241
  description: string;
@@ -260,8 +249,6 @@ export interface MissionDetail {
260
249
  taskGroup?: string;
261
250
  attr?: string;
262
251
  resources?: TemplateTaskResource[];
263
- visibleSc?: boolean;
264
- visibleRoadmap?: boolean;
265
252
  }>;
266
253
  resources?: TemplateMissionResource[];
267
254
  }
@@ -11,4 +11,3 @@ 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,4 +82,3 @@ 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,11 +1,10 @@
1
1
  import type { GradeTemplateFilters, CreateGradeTemplateInput, CreateGradeTemplateMissionInput, AddGradeTemplateToRoadmapInput } from "../../core/gradeTemplates";
2
- export type { GradeTemplateFilters } from "../../core/gradeTemplates";
3
2
  export declare const gradeTemplateKeys: {
4
3
  all: readonly ["gradeTemplates"];
5
4
  list: (filters?: GradeTemplateFilters) => readonly ["gradeTemplates", "list", GradeTemplateFilters | undefined];
6
5
  detail: (id: string) => readonly ["gradeTemplates", "detail", string];
7
6
  };
8
- export declare function useGradeTemplates(filters?: GradeTemplateFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/gradeTemplates").GradeTemplateBrief[], Error>;
7
+ export declare function useGradeTemplates(filters?: GradeTemplateFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/gradeTemplates").GradeTemplate[], Error>;
9
8
  export declare function useGradeTemplate(id: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/gradeTemplates").GradeTemplate, Error>;
10
9
  export declare function useCreateGradeTemplate(): import("@tanstack/react-query").UseMutationResult<import("../../core/gradeTemplates").GradeTemplate, Error, CreateGradeTemplateInput, unknown>;
11
10
  export declare function useDeleteGradeTemplate(): import("@tanstack/react-query").UseMutationResult<void, Error, string, 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.all,
46
+ queryKey: exports.gradeTemplateKeys.list(),
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.all,
58
+ queryKey: exports.gradeTemplateKeys.list(),
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, "limit" | "start"> | undefined];
6
+ missionsInfinite: (filters?: Omit<TemplateMissionFilters, "start" | "limit">) => readonly ["missionLibrary", "missions", "infinite", Omit<TemplateMissionFilters, "start" | "limit"> | undefined];
7
7
  tasks: (filters?: TemplateTaskFilters) => readonly ["missionLibrary", "tasks", TemplateTaskFilters | undefined];
8
- tasksInfinite: (filters?: Omit<TemplateTaskFilters, "start" | "limit">) => readonly ["missionLibrary", "tasks", "infinite", Omit<TemplateTaskFilters, "limit" | "start"> | undefined];
8
+ tasksInfinite: (filters?: Omit<TemplateTaskFilters, "start" | "limit">) => readonly ["missionLibrary", "tasks", "infinite", Omit<TemplateTaskFilters, "start" | "limit"> | 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>;
@@ -5,11 +5,11 @@ 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, "limit" | "start"> | undefined];
8
+ infinite: (userId: string, filters?: Omit<MissionFilters, "start" | "limit">) => readonly ["missions", "infinite", string, Omit<MissionFilters, "start" | "limit"> | undefined];
9
9
  details: () => readonly ["missions", "detail"];
10
10
  detail: (id: string) => readonly ["missions", "detail", string];
11
11
  };
12
- export declare function useMissions(userId: string | null, enabled: boolean): import("@tanstack/react-query").UseQueryResult<Mission[], Error>;
12
+ export declare function useMissions(userId: string | null, enabled: boolean, filters?: MissionFilters): import("@tanstack/react-query").UseQueryResult<Mission[], Error>;
13
13
  /**
14
14
  * Infinite query hook for paginated mission loading
15
15
  */
@@ -20,7 +20,10 @@ export declare function useMissionsInfinite(userId: string | null, filters?: Omi
20
20
  export interface OptimisticOptions {
21
21
  optimistic?: boolean;
22
22
  }
23
- export declare function useCreateMission(options?: OptimisticOptions): import("@tanstack/react-query").UseMutationResult<Mission, Error, Partial<Mission>, {
23
+ export declare function useCreateMission(options?: OptimisticOptions): import("@tanstack/react-query").UseMutationResult<Mission, Error, Partial<Mission> & {
24
+ visibleSc?: boolean;
25
+ visibleRoadmap?: boolean;
26
+ }, {
24
27
  previousMissions: Mission[] | undefined;
25
28
  } | undefined>;
26
29
  export declare function useUpdateMission(options?: OptimisticOptions): import("@tanstack/react-query").UseMutationResult<Mission, Error, {
@@ -27,7 +27,7 @@ exports.missionKeys = {
27
27
  details: () => [...exports.missionKeys.all, "detail"],
28
28
  detail: (id) => [...exports.missionKeys.details(), id],
29
29
  };
30
- function useMissions(userId, enabled) {
30
+ function useMissions(userId, enabled, filters) {
31
31
  const client = (0, provider_1.useCrimsonClient)();
32
32
  return (0, react_query_1.useQuery)({
33
33
  queryKey: exports.missionKeys.list(userId || ""),
@@ -36,7 +36,7 @@ function useMissions(userId, enabled) {
36
36
  throw new Error("Missing userId");
37
37
  }
38
38
  // Without pagination params, list() returns MissionsCategory[]
39
- const categories = (yield client.missions.list(userId));
39
+ const categories = (yield client.missions.list(userId, filters));
40
40
  return categories.flatMap((category) => category.missions || []);
41
41
  }),
42
42
  enabled: !!userId && enabled,
@@ -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, "limit" | "start"> | undefined];
8
+ infinite: (roadmapId: string, userId: string, filters?: Omit<TaskFilters, "start" | "limit">) => readonly ["tasks", "infinite", string, string, Omit<TaskFilters, "start" | "limit"> | 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];
@@ -27,11 +27,17 @@ export declare function useTaskActivities(actionItemIds: string[], type?: string
27
27
  isLoading: boolean;
28
28
  };
29
29
  export declare function useAllUserTasks(missionLinkIds: string[], enabled: boolean): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
30
- export declare function useTasksByRoadmapId(roadmapId: string | null, userId: string | null, enabled: boolean): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
30
+ export declare function useTasksByRoadmapId(roadmapId: string | null, userId: string | null, enabled: boolean, filters: {
31
+ visibleSc?: boolean;
32
+ visibleRoadmap?: boolean;
33
+ }): import("@tanstack/react-query").UseQueryResult<Task[], Error>;
31
34
  /**
32
35
  * Infinite query hook for paginated task loading (requires roadmapId)
33
36
  */
34
- export declare function useTasksInfinite(roadmapId: string | null, userId: string | null, filters?: Omit<TaskFilters, "start" | "limit">, options?: {
37
+ export declare function useTasksInfinite(roadmapId: string | null, userId: string | null, filters: Omit<TaskFilters, "start" | "limit"> & {
38
+ visibleSc?: boolean;
39
+ visibleRoadmap?: boolean;
40
+ }, options?: {
35
41
  enabled?: boolean;
36
42
  pageSize?: number;
37
43
  }): import("@tanstack/react-query").UseInfiniteQueryResult<InfiniteData<PaginatedResult<Task>, unknown>, Error>;
@@ -39,6 +39,94 @@ exports.taskKeys = {
39
39
  activitiesOfTask: (id) => ["task-activities", id],
40
40
  activity: (id, type = "duedate") => [...exports.taskKeys.activitiesOfTask(id), type],
41
41
  };
42
+ function isInfiniteTasksData(data) {
43
+ return (typeof data === "object" &&
44
+ data !== null &&
45
+ "pages" in data &&
46
+ Array.isArray(data.pages));
47
+ }
48
+ function dedupeTasksById(tasks) {
49
+ const seen = new Set();
50
+ return tasks.filter((task) => {
51
+ if (seen.has(task.id))
52
+ return false;
53
+ seen.add(task.id);
54
+ return true;
55
+ });
56
+ }
57
+ function taskMatchesInfiniteFilters(task, filters) {
58
+ var _a;
59
+ if (!filters)
60
+ return true;
61
+ if (((_a = filters.status) === null || _a === void 0 ? void 0 : _a.length) && !filters.status.includes(task.status)) {
62
+ return false;
63
+ }
64
+ if (filters.creatorId && filters.creatorId !== (task.creatorId || task.userId)) {
65
+ return false;
66
+ }
67
+ if (filters.description) {
68
+ const keyword = filters.description.toLowerCase();
69
+ const name = (task.name || "").toLowerCase();
70
+ const description = (task.description || "").toLowerCase();
71
+ if (!name.includes(keyword) && !description.includes(keyword)) {
72
+ return false;
73
+ }
74
+ }
75
+ return true;
76
+ }
77
+ function updateInfiniteQueriesWithCreatedTask(queryClient, createdTask) {
78
+ const infiniteQueries = queryClient.getQueriesData({
79
+ queryKey: [...exports.taskKeys.all, "infinite"],
80
+ });
81
+ infiniteQueries.forEach(([queryKey, queryData]) => {
82
+ if (!isInfiniteTasksData(queryData) || queryData.pages.length === 0) {
83
+ return;
84
+ }
85
+ if (!Array.isArray(queryKey)) {
86
+ return;
87
+ }
88
+ const scope = queryKey[1];
89
+ const queryUserId = queryKey[3];
90
+ const rawFilters = queryKey[4];
91
+ if (scope !== "infinite") {
92
+ return;
93
+ }
94
+ if (typeof queryUserId === "string" && createdTask.userId !== queryUserId) {
95
+ return;
96
+ }
97
+ if (!taskMatchesInfiniteFilters(createdTask, rawFilters)) {
98
+ return;
99
+ }
100
+ queryClient.setQueryData(queryKey, (oldData) => {
101
+ var _a, _b;
102
+ if (!oldData || oldData.pages.length === 0) {
103
+ return oldData;
104
+ }
105
+ const taskAlreadyExists = oldData.pages.some((page) => page.data.some((task) => task.id === createdTask.id));
106
+ if (taskAlreadyExists) {
107
+ return oldData;
108
+ }
109
+ const currentTotal = (_b = (_a = oldData.pages[0]) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.total;
110
+ const nextTotal = typeof currentTotal === "number"
111
+ ? currentTotal + 1
112
+ : oldData.pages.reduce((sum, page) => sum + page.data.length, 0) + 1;
113
+ return Object.assign(Object.assign({}, oldData), { pages: oldData.pages.map((page, pageIndex) => {
114
+ const nextData = pageIndex === 0
115
+ ? dedupeTasksById([createdTask, ...page.data])
116
+ : page.data;
117
+ return Object.assign(Object.assign({}, page), { data: nextData, pagination: page.pagination
118
+ ? Object.assign(Object.assign({}, page.pagination), { total: nextTotal, hasMore: nextTotal > page.pagination.start + page.pagination.limit }) : page.pagination });
119
+ }) });
120
+ });
121
+ });
122
+ }
123
+ function invalidateTaskQueriesExcludingInfinite(queryClient) {
124
+ queryClient.invalidateQueries({ queryKey: exports.taskKeys.lists() });
125
+ queryClient.invalidateQueries({ queryKey: exports.taskKeys.details() });
126
+ queryClient.invalidateQueries({ queryKey: [...exports.taskKeys.all, "roadmap"] });
127
+ queryClient.invalidateQueries({ queryKey: [...exports.taskKeys.all, "missionLinks"] });
128
+ queryClient.invalidateQueries({ queryKey: [...exports.taskKeys.all, "creators"] });
129
+ }
42
130
  function useTasks(missionId, enabled) {
43
131
  const client = (0, provider_1.useCrimsonClient)();
44
132
  return (0, react_query_1.useQuery)({
@@ -149,7 +237,7 @@ function useAllUserTasks(missionLinkIds, enabled) {
149
237
  enabled: enabled && missionLinkIds.length > 0,
150
238
  });
151
239
  }
152
- function useTasksByRoadmapId(roadmapId, userId, enabled) {
240
+ function useTasksByRoadmapId(roadmapId, userId, enabled, filters) {
153
241
  const client = (0, provider_1.useCrimsonClient)();
154
242
  return (0, react_query_1.useQuery)({
155
243
  queryKey: [...exports.taskKeys.all, "roadmap", roadmapId, userId],
@@ -158,7 +246,10 @@ function useTasksByRoadmapId(roadmapId, userId, enabled) {
158
246
  return [];
159
247
  }
160
248
  // Without pagination params, list() returns Task[]
161
- return (yield client.tasks.list({ roadmapId, userId }));
249
+ return (yield client.tasks.list({ roadmapId, userId }, {
250
+ visibleSc: filters.visibleSc,
251
+ visibleRoadmap: filters.visibleRoadmap,
252
+ }));
162
253
  }),
163
254
  enabled: !!roadmapId && !!userId && enabled,
164
255
  });
@@ -224,13 +315,25 @@ function useCreateTask(options) {
224
315
  }
225
316
  return { previousTasks };
226
317
  }),
318
+ onSuccess: (createdTask) => {
319
+ if (createdTask.missionId) {
320
+ queryClient.setQueryData(exports.taskKeys.list(createdTask.missionId), (old) => {
321
+ if (!old)
322
+ return [createdTask];
323
+ if (old.some((task) => task.id === createdTask.id))
324
+ return old;
325
+ return [...old.filter((task) => !task.id.startsWith("temp-")), createdTask];
326
+ });
327
+ }
328
+ updateInfiniteQueriesWithCreatedTask(queryClient, createdTask);
329
+ },
227
330
  onError: (err, newTodo, context) => {
228
331
  if (!optimistic || !(context === null || context === void 0 ? void 0 : context.previousTasks) || !newTodo.missionId)
229
332
  return;
230
333
  queryClient.setQueryData(exports.taskKeys.list(newTodo.missionId), context.previousTasks);
231
334
  },
232
335
  onSettled: () => {
233
- queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
336
+ invalidateTaskQueriesExcludingInfinite(queryClient);
234
337
  },
235
338
  });
236
339
  }
@@ -278,7 +381,12 @@ function useUpdateTask(options) {
278
381
  });
279
382
  },
280
383
  onSettled: (data, error, variables) => {
281
- queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
384
+ if (optimistic) {
385
+ invalidateTaskQueriesExcludingInfinite(queryClient);
386
+ }
387
+ else {
388
+ queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
389
+ }
282
390
  if (variables.id) {
283
391
  queryClient.invalidateQueries({
284
392
  queryKey: exports.taskKeys.activitiesOfTask(variables.id),
@@ -330,7 +438,12 @@ function useDeleteTask(options) {
330
438
  });
331
439
  },
332
440
  onSettled: () => {
333
- queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
441
+ if (optimistic) {
442
+ invalidateTaskQueriesExcludingInfinite(queryClient);
443
+ }
444
+ else {
445
+ queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
446
+ }
334
447
  },
335
448
  });
336
449
  }
@@ -377,7 +490,12 @@ function useBulkDeleteTasks(options) {
377
490
  });
378
491
  },
379
492
  onSettled: () => {
380
- queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
493
+ if (optimistic) {
494
+ invalidateTaskQueriesExcludingInfinite(queryClient);
495
+ }
496
+ else {
497
+ queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
498
+ }
381
499
  },
382
500
  });
383
501
  }
@@ -424,7 +542,12 @@ function useBulkUpdateTasks(options) {
424
542
  });
425
543
  },
426
544
  onSettled: (data, error, variables) => {
427
- queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
545
+ if (optimistic) {
546
+ invalidateTaskQueriesExcludingInfinite(queryClient);
547
+ }
548
+ else {
549
+ queryClient.invalidateQueries({ queryKey: exports.taskKeys.all });
550
+ }
428
551
  // Invalidate activities for all updated tasks
429
552
  variables.ids.forEach(id => {
430
553
  queryClient.invalidateQueries({ queryKey: exports.taskKeys.activitiesOfTask(id) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crimson-education/sdk",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "Crimson SDK for accessing Crimson App APIs",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",