@crimson-education/sdk 0.2.0
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/README.md +377 -0
- package/dist/core/account.d.ts +14 -0
- package/dist/core/account.js +30 -0
- package/dist/core/auth/index.d.ts +11 -0
- package/dist/core/auth/index.js +25 -0
- package/dist/core/auth/oauth-adapter.d.ts +78 -0
- package/dist/core/auth/oauth-adapter.js +341 -0
- package/dist/core/auth/pkce.d.ts +20 -0
- package/dist/core/auth/pkce.js +112 -0
- package/dist/core/auth/token-manager.d.ts +68 -0
- package/dist/core/auth/token-manager.js +294 -0
- package/dist/core/auth/token-storage.d.ts +46 -0
- package/dist/core/auth/token-storage.js +155 -0
- package/dist/core/auth/types.d.ts +148 -0
- package/dist/core/auth/types.js +15 -0
- package/dist/core/client.d.ts +84 -0
- package/dist/core/client.js +229 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.js +47 -0
- package/dist/core/missionLibrary.d.ts +68 -0
- package/dist/core/missionLibrary.js +143 -0
- package/dist/core/missions.d.ts +45 -0
- package/dist/core/missions.js +140 -0
- package/dist/core/roadmap.d.ts +8 -0
- package/dist/core/roadmap.js +18 -0
- package/dist/core/studentProfile.d.ts +21 -0
- package/dist/core/studentProfile.js +41 -0
- package/dist/core/tasks.d.ts +117 -0
- package/dist/core/tasks.js +288 -0
- package/dist/core/types.d.ts +402 -0
- package/dist/core/types.js +2 -0
- package/dist/core/users.d.ts +21 -0
- package/dist/core/users.js +46 -0
- package/dist/iframe/auth-state.d.ts +7 -0
- package/dist/iframe/auth-state.js +125 -0
- package/dist/iframe/constants.d.ts +8 -0
- package/dist/iframe/constants.js +29 -0
- package/dist/iframe/index.d.ts +5 -0
- package/dist/iframe/index.js +17 -0
- package/dist/iframe/listener.d.ts +2 -0
- package/dist/iframe/listener.js +57 -0
- package/dist/iframe/types.d.ts +18 -0
- package/dist/iframe/types.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +22 -0
- package/dist/react/hooks/index.d.ts +10 -0
- package/dist/react/hooks/index.js +48 -0
- package/dist/react/hooks/useAccount.d.ts +13 -0
- package/dist/react/hooks/useAccount.js +39 -0
- package/dist/react/hooks/useAuthState.d.ts +2 -0
- package/dist/react/hooks/useAuthState.js +18 -0
- package/dist/react/hooks/useMissionLibrary.d.ts +31 -0
- package/dist/react/hooks/useMissionLibrary.js +183 -0
- package/dist/react/hooks/useMissions.d.ts +24 -0
- package/dist/react/hooks/useMissions.js +104 -0
- package/dist/react/hooks/useOAuth.d.ts +94 -0
- package/dist/react/hooks/useOAuth.js +211 -0
- package/dist/react/hooks/useRoadmapContext.d.ts +2 -0
- package/dist/react/hooks/useRoadmapContext.js +29 -0
- package/dist/react/hooks/useStudentProfile.d.ts +24 -0
- package/dist/react/hooks/useStudentProfile.js +65 -0
- package/dist/react/hooks/useTasks.d.ts +26 -0
- package/dist/react/hooks/useTasks.js +137 -0
- package/dist/react/hooks/useUsers.d.ts +9 -0
- package/dist/react/hooks/useUsers.js +50 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +21 -0
- package/dist/react/provider.d.ts +16 -0
- package/dist/react/provider.js +41 -0
- package/package.json +61 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setupIframeListener = setupIframeListener;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
function setupIframeListener(allowedOrigins) {
|
|
6
|
+
if (typeof window === "undefined") {
|
|
7
|
+
return () => { };
|
|
8
|
+
}
|
|
9
|
+
const origins = allowedOrigins || (0, constants_1.getDefaultAllowedOrigins)();
|
|
10
|
+
// Notify parent that iframe is ready
|
|
11
|
+
if (window.self !== window.top && window.parent) {
|
|
12
|
+
try {
|
|
13
|
+
window.parent.postMessage({
|
|
14
|
+
type: "IFRAME_READY",
|
|
15
|
+
source: "new-roadmap-ui",
|
|
16
|
+
timestamp: Date.now(),
|
|
17
|
+
}, "*");
|
|
18
|
+
}
|
|
19
|
+
catch (_a) {
|
|
20
|
+
// Silently fail - parent notification is not critical
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const messageHandler = (event) => {
|
|
24
|
+
if (!origins.includes(event.origin)) {
|
|
25
|
+
console.warn(`[iframe-listener] Rejected unauthorized origin: ${event.origin}`, `Allowed origins:`, origins);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const isLocalhost = event.origin.includes("localhost") || event.origin.includes("127.0.0.1");
|
|
29
|
+
const isHttps = event.origin.startsWith("https://");
|
|
30
|
+
if (!isLocalhost && !isHttps) {
|
|
31
|
+
console.error(`[iframe-listener] Insecure HTTP connection from ${event.origin}`);
|
|
32
|
+
if (process.env.NODE_ENV === "production") {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (event.data && event.data.type === "INIT") {
|
|
37
|
+
const { token, userId, studentId, user } = event.data.payload || {};
|
|
38
|
+
if (token && studentId) {
|
|
39
|
+
window.xprops = {
|
|
40
|
+
token,
|
|
41
|
+
userId,
|
|
42
|
+
studentId,
|
|
43
|
+
user,
|
|
44
|
+
};
|
|
45
|
+
window.dispatchEvent(new CustomEvent(constants_1.XPROPS_READY_EVENT));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.warn("[iframe-listener] Missing token or studentId in INIT message");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
window.addEventListener("message", messageHandler);
|
|
53
|
+
// Return cleanup function
|
|
54
|
+
return () => {
|
|
55
|
+
window.removeEventListener("message", messageHandler);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ZoidProps {
|
|
2
|
+
token: string;
|
|
3
|
+
userId: string;
|
|
4
|
+
studentId: string;
|
|
5
|
+
user?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface AuthState {
|
|
8
|
+
token: string | null;
|
|
9
|
+
userId: string | null;
|
|
10
|
+
studentId: string | null;
|
|
11
|
+
user?: Record<string, unknown>;
|
|
12
|
+
ready: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare global {
|
|
15
|
+
interface Window {
|
|
16
|
+
xprops?: ZoidProps;
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Core layer (framework-agnostic) - backward compatible exports
|
|
18
|
+
__exportStar(require("./core"), exports);
|
|
19
|
+
// iframe layer (postMessage communication)
|
|
20
|
+
__exportStar(require("./iframe"), exports);
|
|
21
|
+
// React layer is available via "@crimson/sdk/react" subpath
|
|
22
|
+
// Do NOT export here to avoid forcing React dependency on non-React consumers
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { useAuthState } from "./useAuthState";
|
|
2
|
+
export { useOAuth, useOAuthCallback } from "./useOAuth";
|
|
3
|
+
export type { UseOAuthResult } from "./useOAuth";
|
|
4
|
+
export { useMissions, useMissionsInfinite, useCreateMission, useUpdateMission, useDeleteMission, missionKeys, } from "./useMissions";
|
|
5
|
+
export { useTasks, useAllUserTasks, useTasksByRoadmapId, useTasksInfinite, useCreateTask, useUpdateTask, useDeleteTask, taskKeys, } from "./useTasks";
|
|
6
|
+
export { useUsers, useUser, userKeys } from "./useUsers";
|
|
7
|
+
export { useCurrentUserRoles, accountKeys } from "./useAccount";
|
|
8
|
+
export { useRoadmapContext } from "./useRoadmapContext";
|
|
9
|
+
export { useTemplateMissions, useTemplateMissionsInfinite, useTemplateTasks, useTemplateTasksInfinite, useTemplateMissionDetail, useCopyTemplateMission, useAssignBulkMission, useAssignBulkTask, useCreateFromPredefinedTasks, missionLibraryKeys, } from "./useMissionLibrary";
|
|
10
|
+
export { useStudentProfile, useStudentPrefilledInfo, studentProfileKeys, } from "./useStudentProfile";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.studentProfileKeys = exports.useStudentPrefilledInfo = exports.useStudentProfile = exports.missionLibraryKeys = exports.useCreateFromPredefinedTasks = exports.useAssignBulkTask = exports.useAssignBulkMission = exports.useCopyTemplateMission = exports.useTemplateMissionDetail = exports.useTemplateTasksInfinite = exports.useTemplateTasks = exports.useTemplateMissionsInfinite = exports.useTemplateMissions = exports.useRoadmapContext = exports.accountKeys = exports.useCurrentUserRoles = exports.userKeys = exports.useUser = exports.useUsers = exports.taskKeys = exports.useDeleteTask = exports.useUpdateTask = exports.useCreateTask = exports.useTasksInfinite = exports.useTasksByRoadmapId = exports.useAllUserTasks = exports.useTasks = exports.missionKeys = exports.useDeleteMission = exports.useUpdateMission = exports.useCreateMission = exports.useMissionsInfinite = exports.useMissions = exports.useOAuthCallback = exports.useOAuth = exports.useAuthState = void 0;
|
|
4
|
+
var useAuthState_1 = require("./useAuthState");
|
|
5
|
+
Object.defineProperty(exports, "useAuthState", { enumerable: true, get: function () { return useAuthState_1.useAuthState; } });
|
|
6
|
+
var useOAuth_1 = require("./useOAuth");
|
|
7
|
+
Object.defineProperty(exports, "useOAuth", { enumerable: true, get: function () { return useOAuth_1.useOAuth; } });
|
|
8
|
+
Object.defineProperty(exports, "useOAuthCallback", { enumerable: true, get: function () { return useOAuth_1.useOAuthCallback; } });
|
|
9
|
+
var useMissions_1 = require("./useMissions");
|
|
10
|
+
Object.defineProperty(exports, "useMissions", { enumerable: true, get: function () { return useMissions_1.useMissions; } });
|
|
11
|
+
Object.defineProperty(exports, "useMissionsInfinite", { enumerable: true, get: function () { return useMissions_1.useMissionsInfinite; } });
|
|
12
|
+
Object.defineProperty(exports, "useCreateMission", { enumerable: true, get: function () { return useMissions_1.useCreateMission; } });
|
|
13
|
+
Object.defineProperty(exports, "useUpdateMission", { enumerable: true, get: function () { return useMissions_1.useUpdateMission; } });
|
|
14
|
+
Object.defineProperty(exports, "useDeleteMission", { enumerable: true, get: function () { return useMissions_1.useDeleteMission; } });
|
|
15
|
+
Object.defineProperty(exports, "missionKeys", { enumerable: true, get: function () { return useMissions_1.missionKeys; } });
|
|
16
|
+
var useTasks_1 = require("./useTasks");
|
|
17
|
+
Object.defineProperty(exports, "useTasks", { enumerable: true, get: function () { return useTasks_1.useTasks; } });
|
|
18
|
+
Object.defineProperty(exports, "useAllUserTasks", { enumerable: true, get: function () { return useTasks_1.useAllUserTasks; } });
|
|
19
|
+
Object.defineProperty(exports, "useTasksByRoadmapId", { enumerable: true, get: function () { return useTasks_1.useTasksByRoadmapId; } });
|
|
20
|
+
Object.defineProperty(exports, "useTasksInfinite", { enumerable: true, get: function () { return useTasks_1.useTasksInfinite; } });
|
|
21
|
+
Object.defineProperty(exports, "useCreateTask", { enumerable: true, get: function () { return useTasks_1.useCreateTask; } });
|
|
22
|
+
Object.defineProperty(exports, "useUpdateTask", { enumerable: true, get: function () { return useTasks_1.useUpdateTask; } });
|
|
23
|
+
Object.defineProperty(exports, "useDeleteTask", { enumerable: true, get: function () { return useTasks_1.useDeleteTask; } });
|
|
24
|
+
Object.defineProperty(exports, "taskKeys", { enumerable: true, get: function () { return useTasks_1.taskKeys; } });
|
|
25
|
+
var useUsers_1 = require("./useUsers");
|
|
26
|
+
Object.defineProperty(exports, "useUsers", { enumerable: true, get: function () { return useUsers_1.useUsers; } });
|
|
27
|
+
Object.defineProperty(exports, "useUser", { enumerable: true, get: function () { return useUsers_1.useUser; } });
|
|
28
|
+
Object.defineProperty(exports, "userKeys", { enumerable: true, get: function () { return useUsers_1.userKeys; } });
|
|
29
|
+
var useAccount_1 = require("./useAccount");
|
|
30
|
+
Object.defineProperty(exports, "useCurrentUserRoles", { enumerable: true, get: function () { return useAccount_1.useCurrentUserRoles; } });
|
|
31
|
+
Object.defineProperty(exports, "accountKeys", { enumerable: true, get: function () { return useAccount_1.accountKeys; } });
|
|
32
|
+
var useRoadmapContext_1 = require("./useRoadmapContext");
|
|
33
|
+
Object.defineProperty(exports, "useRoadmapContext", { enumerable: true, get: function () { return useRoadmapContext_1.useRoadmapContext; } });
|
|
34
|
+
var useMissionLibrary_1 = require("./useMissionLibrary");
|
|
35
|
+
Object.defineProperty(exports, "useTemplateMissions", { enumerable: true, get: function () { return useMissionLibrary_1.useTemplateMissions; } });
|
|
36
|
+
Object.defineProperty(exports, "useTemplateMissionsInfinite", { enumerable: true, get: function () { return useMissionLibrary_1.useTemplateMissionsInfinite; } });
|
|
37
|
+
Object.defineProperty(exports, "useTemplateTasks", { enumerable: true, get: function () { return useMissionLibrary_1.useTemplateTasks; } });
|
|
38
|
+
Object.defineProperty(exports, "useTemplateTasksInfinite", { enumerable: true, get: function () { return useMissionLibrary_1.useTemplateTasksInfinite; } });
|
|
39
|
+
Object.defineProperty(exports, "useTemplateMissionDetail", { enumerable: true, get: function () { return useMissionLibrary_1.useTemplateMissionDetail; } });
|
|
40
|
+
Object.defineProperty(exports, "useCopyTemplateMission", { enumerable: true, get: function () { return useMissionLibrary_1.useCopyTemplateMission; } });
|
|
41
|
+
Object.defineProperty(exports, "useAssignBulkMission", { enumerable: true, get: function () { return useMissionLibrary_1.useAssignBulkMission; } });
|
|
42
|
+
Object.defineProperty(exports, "useAssignBulkTask", { enumerable: true, get: function () { return useMissionLibrary_1.useAssignBulkTask; } });
|
|
43
|
+
Object.defineProperty(exports, "useCreateFromPredefinedTasks", { enumerable: true, get: function () { return useMissionLibrary_1.useCreateFromPredefinedTasks; } });
|
|
44
|
+
Object.defineProperty(exports, "missionLibraryKeys", { enumerable: true, get: function () { return useMissionLibrary_1.missionLibraryKeys; } });
|
|
45
|
+
var useStudentProfile_1 = require("./useStudentProfile");
|
|
46
|
+
Object.defineProperty(exports, "useStudentProfile", { enumerable: true, get: function () { return useStudentProfile_1.useStudentProfile; } });
|
|
47
|
+
Object.defineProperty(exports, "useStudentPrefilledInfo", { enumerable: true, get: function () { return useStudentProfile_1.useStudentPrefilledInfo; } });
|
|
48
|
+
Object.defineProperty(exports, "studentProfileKeys", { enumerable: true, get: function () { return useStudentProfile_1.studentProfileKeys; } });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CurrentUserRoles } from "../../core/types";
|
|
2
|
+
export declare const accountKeys: {
|
|
3
|
+
all: readonly ["account"];
|
|
4
|
+
currentUserRoles: () => readonly ["account", "currentUserRoles"];
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Hook to get current user's roles
|
|
8
|
+
*
|
|
9
|
+
* @returns Query result containing:
|
|
10
|
+
* - userId: The user's ID
|
|
11
|
+
* - roles: Array of role objects with roleId and isPrimary flag
|
|
12
|
+
*/
|
|
13
|
+
export declare function useCurrentUserRoles(enabled?: boolean): import("@tanstack/react-query").UseQueryResult<CurrentUserRoles, Error>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.accountKeys = void 0;
|
|
14
|
+
exports.useCurrentUserRoles = useCurrentUserRoles;
|
|
15
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
16
|
+
const provider_1 = require("../provider");
|
|
17
|
+
// Query keys
|
|
18
|
+
exports.accountKeys = {
|
|
19
|
+
all: ["account"],
|
|
20
|
+
currentUserRoles: () => [...exports.accountKeys.all, "currentUserRoles"],
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Hook to get current user's roles
|
|
24
|
+
*
|
|
25
|
+
* @returns Query result containing:
|
|
26
|
+
* - userId: The user's ID
|
|
27
|
+
* - roles: Array of role objects with roleId and isPrimary flag
|
|
28
|
+
*/
|
|
29
|
+
function useCurrentUserRoles(enabled = true) {
|
|
30
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
31
|
+
return (0, react_query_1.useQuery)({
|
|
32
|
+
queryKey: exports.accountKeys.currentUserRoles(),
|
|
33
|
+
queryFn: () => __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
return client.account.getCurrentUserRoles();
|
|
35
|
+
}),
|
|
36
|
+
enabled,
|
|
37
|
+
staleTime: 1000 * 60 * 5, // 5 minutes - roles don't change often
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useAuthState = useAuthState;
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const iframe_1 = require("../../iframe");
|
|
7
|
+
const emptyState = {
|
|
8
|
+
token: null,
|
|
9
|
+
userId: null,
|
|
10
|
+
studentId: null,
|
|
11
|
+
user: undefined,
|
|
12
|
+
ready: false,
|
|
13
|
+
};
|
|
14
|
+
// Server snapshot always returns empty state to ensure consistent SSR
|
|
15
|
+
const getServerSnapshot = () => emptyState;
|
|
16
|
+
function useAuthState() {
|
|
17
|
+
return (0, react_1.useSyncExternalStore)(iframe_1.subscribeToAuthState, iframe_1.getAuthState, getServerSnapshot);
|
|
18
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TemplateMission, TemplateTask, MissionDetail, AssignBulkMissionInput, AssignBulkTaskInput } from "../../core/types";
|
|
2
|
+
import type { TemplateMissionFilters, TemplateTaskFilters, CopyTemplateMissionInput, CreateFromPredefinedInput } from "../../core/missionLibrary";
|
|
3
|
+
export declare const missionLibraryKeys: {
|
|
4
|
+
all: readonly ["missionLibrary"];
|
|
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];
|
|
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];
|
|
9
|
+
missionDetail: (id: string) => readonly ["missionLibrary", "mission", string];
|
|
10
|
+
};
|
|
11
|
+
export declare function useTemplateMissions(filters?: TemplateMissionFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/types").PaginatedResult<TemplateMission>, Error>;
|
|
12
|
+
export declare function useTemplateMissionsInfinite(filters?: Omit<TemplateMissionFilters, "start" | "limit">, options?: {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
pageSize?: number;
|
|
15
|
+
}): import("@tanstack/react-query").UseInfiniteQueryResult<import("@tanstack/react-query").InfiniteData<import("../../core/types").PaginatedResult<TemplateMission>, unknown>, Error>;
|
|
16
|
+
export declare function useTemplateTasks(filters?: TemplateTaskFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("../../core/types").PaginatedResult<TemplateTask>, Error>;
|
|
17
|
+
export declare function useTemplateTasksInfinite(filters?: Omit<TemplateTaskFilters, "start" | "limit">, options?: {
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
pageSize?: number;
|
|
20
|
+
}): import("@tanstack/react-query").UseInfiniteQueryResult<import("@tanstack/react-query").InfiniteData<import("../../core/types").PaginatedResult<TemplateTask>, unknown>, Error>;
|
|
21
|
+
export declare function useTemplateMissionDetail(missionId: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<MissionDetail | null, Error>;
|
|
22
|
+
export declare function useCopyTemplateMission(): import("@tanstack/react-query").UseMutationResult<TemplateMission[], Error, CopyTemplateMissionInput, unknown>;
|
|
23
|
+
export declare function useAssignBulkMission(): import("@tanstack/react-query").UseMutationResult<{
|
|
24
|
+
code: number;
|
|
25
|
+
msg?: string;
|
|
26
|
+
}, Error, AssignBulkMissionInput[], unknown>;
|
|
27
|
+
export declare function useAssignBulkTask(): import("@tanstack/react-query").UseMutationResult<{
|
|
28
|
+
code: number;
|
|
29
|
+
msg?: string;
|
|
30
|
+
}, Error, AssignBulkTaskInput[], unknown>;
|
|
31
|
+
export declare function useCreateFromPredefinedTasks(): import("@tanstack/react-query").UseMutationResult<TemplateTask[], Error, CreateFromPredefinedInput, unknown>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.missionLibraryKeys = void 0;
|
|
14
|
+
exports.useTemplateMissions = useTemplateMissions;
|
|
15
|
+
exports.useTemplateMissionsInfinite = useTemplateMissionsInfinite;
|
|
16
|
+
exports.useTemplateTasks = useTemplateTasks;
|
|
17
|
+
exports.useTemplateTasksInfinite = useTemplateTasksInfinite;
|
|
18
|
+
exports.useTemplateMissionDetail = useTemplateMissionDetail;
|
|
19
|
+
exports.useCopyTemplateMission = useCopyTemplateMission;
|
|
20
|
+
exports.useAssignBulkMission = useAssignBulkMission;
|
|
21
|
+
exports.useAssignBulkTask = useAssignBulkTask;
|
|
22
|
+
exports.useCreateFromPredefinedTasks = useCreateFromPredefinedTasks;
|
|
23
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
24
|
+
const provider_1 = require("../provider");
|
|
25
|
+
const useMissions_1 = require("./useMissions");
|
|
26
|
+
const useTasks_1 = require("./useTasks");
|
|
27
|
+
// Query keys
|
|
28
|
+
exports.missionLibraryKeys = {
|
|
29
|
+
all: ["missionLibrary"],
|
|
30
|
+
missions: (filters) => [...exports.missionLibraryKeys.all, "missions", filters],
|
|
31
|
+
missionsInfinite: (filters) => [...exports.missionLibraryKeys.all, "missions", "infinite", filters],
|
|
32
|
+
tasks: (filters) => [...exports.missionLibraryKeys.all, "tasks", filters],
|
|
33
|
+
tasksInfinite: (filters) => [...exports.missionLibraryKeys.all, "tasks", "infinite", filters],
|
|
34
|
+
missionDetail: (id) => [...exports.missionLibraryKeys.all, "mission", id],
|
|
35
|
+
};
|
|
36
|
+
// --- Template Missions ---
|
|
37
|
+
function useTemplateMissions(filters, enabled = true) {
|
|
38
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
39
|
+
return (0, react_query_1.useQuery)({
|
|
40
|
+
queryKey: exports.missionLibraryKeys.missions(filters),
|
|
41
|
+
queryFn: () => client.library.listTemplateMissions(filters),
|
|
42
|
+
enabled,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function useTemplateMissionsInfinite(filters, options) {
|
|
46
|
+
var _a, _b;
|
|
47
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
48
|
+
const enabled = (_a = options === null || options === void 0 ? void 0 : options.enabled) !== null && _a !== void 0 ? _a : true;
|
|
49
|
+
const pageSize = (_b = options === null || options === void 0 ? void 0 : options.pageSize) !== null && _b !== void 0 ? _b : 20;
|
|
50
|
+
return (0, react_query_1.useInfiniteQuery)({
|
|
51
|
+
queryKey: exports.missionLibraryKeys.missionsInfinite(filters),
|
|
52
|
+
queryFn: (_a) => __awaiter(this, [_a], void 0, function* ({ pageParam = 0 }) {
|
|
53
|
+
return client.library.listTemplateMissions(Object.assign(Object.assign({}, filters), { start: pageParam, limit: pageSize }));
|
|
54
|
+
}),
|
|
55
|
+
initialPageParam: 0,
|
|
56
|
+
getNextPageParam: (lastPage) => {
|
|
57
|
+
if (!(lastPage === null || lastPage === void 0 ? void 0 : lastPage.pagination))
|
|
58
|
+
return undefined;
|
|
59
|
+
return lastPage.pagination.hasMore
|
|
60
|
+
? lastPage.pagination.start + lastPage.pagination.limit
|
|
61
|
+
: undefined;
|
|
62
|
+
},
|
|
63
|
+
enabled,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// --- Template Tasks ---
|
|
67
|
+
function useTemplateTasks(filters, enabled = true) {
|
|
68
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
69
|
+
return (0, react_query_1.useQuery)({
|
|
70
|
+
queryKey: exports.missionLibraryKeys.tasks(filters),
|
|
71
|
+
queryFn: () => client.library.listTemplateTasks(filters),
|
|
72
|
+
enabled,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function useTemplateTasksInfinite(filters, options) {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
78
|
+
const enabled = (_a = options === null || options === void 0 ? void 0 : options.enabled) !== null && _a !== void 0 ? _a : true;
|
|
79
|
+
const pageSize = (_b = options === null || options === void 0 ? void 0 : options.pageSize) !== null && _b !== void 0 ? _b : 20;
|
|
80
|
+
return (0, react_query_1.useInfiniteQuery)({
|
|
81
|
+
queryKey: exports.missionLibraryKeys.tasksInfinite(filters),
|
|
82
|
+
queryFn: (_a) => __awaiter(this, [_a], void 0, function* ({ pageParam = 0 }) {
|
|
83
|
+
return client.library.listTemplateTasks(Object.assign(Object.assign({}, filters), { start: pageParam, limit: pageSize }));
|
|
84
|
+
}),
|
|
85
|
+
initialPageParam: 0,
|
|
86
|
+
getNextPageParam: (lastPage) => {
|
|
87
|
+
if (!(lastPage === null || lastPage === void 0 ? void 0 : lastPage.pagination))
|
|
88
|
+
return undefined;
|
|
89
|
+
return lastPage.pagination.hasMore
|
|
90
|
+
? lastPage.pagination.start + lastPage.pagination.limit
|
|
91
|
+
: undefined;
|
|
92
|
+
},
|
|
93
|
+
enabled,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// --- Mission Detail ---
|
|
97
|
+
function useTemplateMissionDetail(missionId, enabled = true) {
|
|
98
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
99
|
+
return (0, react_query_1.useQuery)({
|
|
100
|
+
queryKey: exports.missionLibraryKeys.missionDetail(missionId),
|
|
101
|
+
queryFn: () => client.library.getMissionById(missionId),
|
|
102
|
+
enabled: !!missionId && enabled,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// --- Mutations ---
|
|
106
|
+
function useCopyTemplateMission() {
|
|
107
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
108
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
109
|
+
return (0, react_query_1.useMutation)({
|
|
110
|
+
mutationFn: (input) => client.library.copyTemplateMission(input),
|
|
111
|
+
onSuccess: (_, variables) => {
|
|
112
|
+
queryClient.invalidateQueries({
|
|
113
|
+
queryKey: useMissions_1.missionKeys.list(variables.userId),
|
|
114
|
+
});
|
|
115
|
+
queryClient.invalidateQueries({
|
|
116
|
+
queryKey: [...useMissions_1.missionKeys.all, "infinite", variables.userId],
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function useAssignBulkMission() {
|
|
122
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
123
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
124
|
+
return (0, react_query_1.useMutation)({
|
|
125
|
+
mutationFn: (input) => client.library.assignBulkMission(input),
|
|
126
|
+
onSuccess: (_, variables) => {
|
|
127
|
+
const uniqueUsers = Array.from(new Set(variables.map((v) => v.studentUid)));
|
|
128
|
+
uniqueUsers.forEach((userId) => {
|
|
129
|
+
queryClient.invalidateQueries({
|
|
130
|
+
queryKey: useMissions_1.missionKeys.list(userId),
|
|
131
|
+
});
|
|
132
|
+
queryClient.invalidateQueries({
|
|
133
|
+
queryKey: [...useMissions_1.missionKeys.all, "infinite", userId],
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function useAssignBulkTask() {
|
|
140
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
141
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
142
|
+
return (0, react_query_1.useMutation)({
|
|
143
|
+
mutationFn: (input) => client.library.assignBulkTask(input),
|
|
144
|
+
onSuccess: (_, variables) => {
|
|
145
|
+
const uniqueInfiniteKeys = new Set();
|
|
146
|
+
const uniqueMissionIds = new Set();
|
|
147
|
+
variables.forEach((input) => {
|
|
148
|
+
const userId = input.studentUid;
|
|
149
|
+
input.tasks.forEach((task) => {
|
|
150
|
+
const roadmapId = task.mission.roadmapId;
|
|
151
|
+
const missionId = task.mission.id;
|
|
152
|
+
uniqueInfiniteKeys.add(`${roadmapId}|${userId}`);
|
|
153
|
+
if (missionId) {
|
|
154
|
+
uniqueMissionIds.add(missionId);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
uniqueInfiniteKeys.forEach((key) => {
|
|
159
|
+
const [roadmapId, userId] = key.split("|");
|
|
160
|
+
queryClient.invalidateQueries({
|
|
161
|
+
queryKey: [...useTasks_1.taskKeys.all, "infinite", roadmapId, userId],
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
uniqueMissionIds.forEach((missionId) => {
|
|
165
|
+
queryClient.invalidateQueries({
|
|
166
|
+
queryKey: useTasks_1.taskKeys.list(missionId),
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function useCreateFromPredefinedTasks() {
|
|
173
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
174
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
175
|
+
return (0, react_query_1.useMutation)({
|
|
176
|
+
mutationFn: (input) => client.library.createFromPredefinedTasks(input),
|
|
177
|
+
onSuccess: (_, variables) => {
|
|
178
|
+
queryClient.invalidateQueries({
|
|
179
|
+
queryKey: useTasks_1.taskKeys.list(variables.missionId),
|
|
180
|
+
});
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Mission, PaginatedResult } from "../../core/types";
|
|
2
|
+
import type { MissionFilters } from "../../core/missions";
|
|
3
|
+
export declare const missionKeys: {
|
|
4
|
+
all: readonly ["missions"];
|
|
5
|
+
lists: () => readonly ["missions", "list"];
|
|
6
|
+
list: (userId: string) => readonly ["missions", "list", string];
|
|
7
|
+
infinite: (userId: string, filters?: Omit<MissionFilters, "start" | "limit">) => readonly ["missions", "infinite", string, Omit<MissionFilters, "start" | "limit"> | undefined];
|
|
8
|
+
details: () => readonly ["missions", "detail"];
|
|
9
|
+
detail: (id: string) => readonly ["missions", "detail", string];
|
|
10
|
+
};
|
|
11
|
+
export declare function useMissions(userId: string | null, enabled: boolean): import("@tanstack/react-query").UseQueryResult<Mission[], Error>;
|
|
12
|
+
/**
|
|
13
|
+
* Infinite query hook for paginated mission loading
|
|
14
|
+
*/
|
|
15
|
+
export declare function useMissionsInfinite(userId: string | null, filters?: Omit<MissionFilters, "start" | "limit">, options?: {
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
pageSize?: number;
|
|
18
|
+
}): import("@tanstack/react-query").UseInfiniteQueryResult<import("@tanstack/react-query").InfiniteData<PaginatedResult<Mission>, unknown>, Error>;
|
|
19
|
+
export declare function useCreateMission(): import("@tanstack/react-query").UseMutationResult<Mission, Error, Partial<Mission>, unknown>;
|
|
20
|
+
export declare function useUpdateMission(): import("@tanstack/react-query").UseMutationResult<Mission, Error, {
|
|
21
|
+
id: string;
|
|
22
|
+
data: Partial<Mission>;
|
|
23
|
+
}, unknown>;
|
|
24
|
+
export declare function useDeleteMission(): import("@tanstack/react-query").UseMutationResult<void, Error, string, unknown>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.missionKeys = void 0;
|
|
14
|
+
exports.useMissions = useMissions;
|
|
15
|
+
exports.useMissionsInfinite = useMissionsInfinite;
|
|
16
|
+
exports.useCreateMission = useCreateMission;
|
|
17
|
+
exports.useUpdateMission = useUpdateMission;
|
|
18
|
+
exports.useDeleteMission = useDeleteMission;
|
|
19
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
20
|
+
const provider_1 = require("../provider");
|
|
21
|
+
// Query keys
|
|
22
|
+
exports.missionKeys = {
|
|
23
|
+
all: ["missions"],
|
|
24
|
+
lists: () => [...exports.missionKeys.all, "list"],
|
|
25
|
+
list: (userId) => [...exports.missionKeys.lists(), userId],
|
|
26
|
+
infinite: (userId, filters) => [...exports.missionKeys.all, "infinite", userId, filters],
|
|
27
|
+
details: () => [...exports.missionKeys.all, "detail"],
|
|
28
|
+
detail: (id) => [...exports.missionKeys.details(), id],
|
|
29
|
+
};
|
|
30
|
+
function useMissions(userId, enabled) {
|
|
31
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
32
|
+
return (0, react_query_1.useQuery)({
|
|
33
|
+
queryKey: exports.missionKeys.list(userId || ""),
|
|
34
|
+
queryFn: () => __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
if (!userId) {
|
|
36
|
+
throw new Error("Missing userId");
|
|
37
|
+
}
|
|
38
|
+
// Without pagination params, list() returns MissionsCategory[]
|
|
39
|
+
const categories = (yield client.missions.list(userId));
|
|
40
|
+
return categories.flatMap((category) => category.missions || []);
|
|
41
|
+
}),
|
|
42
|
+
enabled: !!userId && enabled,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Infinite query hook for paginated mission loading
|
|
47
|
+
*/
|
|
48
|
+
function useMissionsInfinite(userId, filters, options) {
|
|
49
|
+
var _a, _b;
|
|
50
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
51
|
+
const enabled = (_a = options === null || options === void 0 ? void 0 : options.enabled) !== null && _a !== void 0 ? _a : true;
|
|
52
|
+
const pageSize = (_b = options === null || options === void 0 ? void 0 : options.pageSize) !== null && _b !== void 0 ? _b : 20;
|
|
53
|
+
return (0, react_query_1.useInfiniteQuery)({
|
|
54
|
+
queryKey: exports.missionKeys.infinite(userId || "", filters),
|
|
55
|
+
queryFn: (_a) => __awaiter(this, [_a], void 0, function* ({ pageParam = 0 }) {
|
|
56
|
+
if (!userId) {
|
|
57
|
+
throw new Error("Missing userId");
|
|
58
|
+
}
|
|
59
|
+
return client.missions.listPaginated(userId, filters, {
|
|
60
|
+
start: pageParam,
|
|
61
|
+
limit: pageSize,
|
|
62
|
+
});
|
|
63
|
+
}),
|
|
64
|
+
initialPageParam: 0,
|
|
65
|
+
getNextPageParam: (lastPage) => {
|
|
66
|
+
if (!(lastPage === null || lastPage === void 0 ? void 0 : lastPage.pagination))
|
|
67
|
+
return undefined;
|
|
68
|
+
return lastPage.pagination.hasMore
|
|
69
|
+
? lastPage.pagination.start + lastPage.pagination.limit
|
|
70
|
+
: undefined;
|
|
71
|
+
},
|
|
72
|
+
enabled: !!userId && enabled,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function useCreateMission() {
|
|
76
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
77
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
78
|
+
return (0, react_query_1.useMutation)({
|
|
79
|
+
mutationFn: (data) => client.missions.create(data),
|
|
80
|
+
onSuccess: () => {
|
|
81
|
+
queryClient.invalidateQueries({ queryKey: exports.missionKeys.all });
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function useUpdateMission() {
|
|
86
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
87
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
88
|
+
return (0, react_query_1.useMutation)({
|
|
89
|
+
mutationFn: ({ id, data }) => client.missions.update(id, data),
|
|
90
|
+
onSuccess: () => {
|
|
91
|
+
queryClient.invalidateQueries({ queryKey: exports.missionKeys.all });
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function useDeleteMission() {
|
|
96
|
+
const client = (0, provider_1.useCrimsonClient)();
|
|
97
|
+
const queryClient = (0, react_query_1.useQueryClient)();
|
|
98
|
+
return (0, react_query_1.useMutation)({
|
|
99
|
+
mutationFn: (id) => client.missions.delete(id),
|
|
100
|
+
onSuccess: () => {
|
|
101
|
+
queryClient.invalidateQueries({ queryKey: exports.missionKeys.all });
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|