testforce-engine 0.0.3-alpha → 1.0.0-beta-1

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/dist/index.d.mts CHANGED
@@ -1,4 +1,22 @@
1
- import React, { PropsWithChildren } from 'react';
1
+ import React from 'react';
2
+
3
+ declare enum AttemptStatus {
4
+ ATTEMPTED = "ATTEMPTED",
5
+ NOT_ATTEMPTED = "NOT_ATTEMPTED",
6
+ NOT_VISITED = "NOT_VISITED",
7
+ MARKED_FOR_REVIEW = "MARKED_FOR_REVIEW",
8
+ ATTEMPTED_AND_MARKED_FOR_REVIEW = "ATTEMPTED_AND_MARKED_FOR_REVIEW",
9
+ ACITVE_QUESTION = "ACITVE_QUESTION"
10
+ }
11
+ interface UserSettings {
12
+ selectedFilter?: AttemptStatus;
13
+ }
14
+ interface SolutionDetails$1 {
15
+ markedSolution?: string[];
16
+ markedForReview?: boolean;
17
+ timeTaken?: number;
18
+ isSaved?: boolean;
19
+ }
2
20
 
3
21
  declare enum TestType {
4
22
  QUIZ = "QUIZ",
@@ -21,6 +39,10 @@ declare enum TestStatus {
21
39
  NOT_STARTED = "NotStarted",
22
40
  ENDED = "Ended"
23
41
  }
42
+ declare enum ProctoringType {
43
+ BASIC = "basic",
44
+ AI = "ai"
45
+ }
24
46
  interface Test {
25
47
  name: string;
26
48
  type: TestType;
@@ -46,6 +68,8 @@ interface Test {
46
68
  status: TestStatus;
47
69
  lastVisitedQuestionId: string;
48
70
  timeTaken: Record<string, any>;
71
+ publishedAt: Date;
72
+ proctoring: ProctoringType;
49
73
  }
50
74
  interface Section {
51
75
  name: string;
@@ -73,9 +97,10 @@ interface Question {
73
97
  solutionDescription?: string;
74
98
  displayOrder: number;
75
99
  duration: number;
76
- questionResponse: SolutionDetails$1;
100
+ questionResponse: SolutionDetails;
101
+ imageUrl: string;
77
102
  }
78
- interface SolutionDetails$1 {
103
+ interface SolutionDetails {
79
104
  markedSolution?: string[];
80
105
  markedForReview?: boolean;
81
106
  timeTaken?: number;
@@ -85,99 +110,82 @@ interface Option {
85
110
  _id: string;
86
111
  }
87
112
 
88
- declare enum AttemptStatus {
89
- ATTEMPTED = "ATTEMPTED",
90
- NOT_ATTEMPTED = "NOT_ATTEMPTED",
91
- NOT_VISITED = "NOT_VISITED",
92
- MARKED_FOR_REVIEW = "MARKED_FOR_REVIEW",
93
- ATTEMPTED_AND_MARKED_FOR_REVIEW = "ATTEMPTED_AND_MARKED_FOR_REVIEW",
94
- ACITVE_QUESTION = "ACITVE_QUESTION"
95
- }
96
- interface UserSettings {
97
- selectedFilter?: AttemptStatus;
98
- }
99
- interface SolutionDetails {
100
- markedSolution?: string[];
101
- markedForReview?: boolean;
102
- timeTaken?: number;
103
- isSaved?: boolean;
104
- }
105
- interface SubmitTest {
106
- payload: Record<string, any>;
107
- pause: boolean;
108
- autoSubmit: boolean;
109
- }
110
-
111
- declare const TestEngineProvider: ({ test, submitTest, ...props }: {
112
- test: Test;
113
- isSolution?: boolean;
114
- submitTest: React.Dispatch<SubmitTest>;
115
- } & PropsWithChildren) => React.JSX.Element;
116
-
117
113
  declare const useTestEngine: () => {
118
- currentSection: Section | undefined;
119
- currentQuestion: Question | undefined;
120
- handleSubmitTest: (pause?: boolean, autoSubmit?: boolean) => Promise<Record<string, any>>;
121
- handleUpdateTestDetails: (value: Test) => void;
122
- handleUpdateQuestionCoordinates: (value: {
123
- currentQuestionIndex: number;
124
- currentSectionIndex: number;
125
- }) => Promise<void>;
126
- handleUpdateSolutions: (value: Record<string, SolutionDetails>) => void;
127
- handleUpdateCurrentAnswer: (value: SolutionDetails) => void;
128
- handleUpdateUserSettings: (value: UserSettings) => void;
129
- handleResetLocal: () => Promise<void>;
130
114
  test: Test | undefined;
131
- solutions: Record<string, SolutionDetails>;
115
+ solutions: Record<string, SolutionDetails$1>;
132
116
  currentQuestionIndex: number;
133
117
  currentSectionIndex: number;
134
- currentQuestionAnswer: SolutionDetails | undefined;
118
+ currentQuestionAnswer: SolutionDetails$1 | undefined;
135
119
  userSettings: UserSettings | undefined;
136
120
  isSolution?: boolean;
137
121
  submitting?: boolean;
122
+ timer: Record<string, number>;
123
+ isHydrated: boolean;
124
+ setTest: (test: Test, shouldUpdateSolution: boolean) => void;
125
+ setQuestionCoordinates: (sectionIndex: number, questionIndex: number) => void;
126
+ setSolution: (questionId: string, details: SolutionDetails$1) => void;
127
+ setCurrentAnswer: (answer: SolutionDetails$1 | undefined) => void;
128
+ setUserSettings: (settings: UserSettings) => void;
129
+ setTestSubmitting: (submitting: boolean) => void;
130
+ incrementTimer: (quesId: string) => void;
131
+ decrementTimer: (testId: string) => void;
132
+ reset: () => void;
133
+ setIsHydrated: (isHydrated: boolean) => void;
134
+ handleSubmitTest: (pause?: boolean, autoSubmit?: boolean) => Record<string, any>;
135
+ currentSection: Section | undefined;
136
+ currentQuestion: Question | undefined;
138
137
  };
139
138
 
140
- declare const useTestEngineBody: () => {
141
- isQuizAnswer: boolean;
142
- handleClearResponse: () => void;
143
- handleSelectOption: (optionId: string) => void;
144
- handleIntegerInputChange: (val: string) => void;
145
- handleMarkForReview: () => void;
146
- };
147
-
148
- declare const useTestEngineFooter: () => {
149
- handleNext: () => void;
150
- handlePrevious: () => void;
151
- handleSaveAnswer: () => void;
152
- handleMarkForReview: () => void;
153
- isLastQuestion: boolean;
154
- isFirstQuestion: boolean;
139
+ declare const useTestTimer: () => {
140
+ timer: number;
155
141
  };
156
142
 
157
- declare const useTestQuestionStatus: ({ includeAllSections, }?: {
143
+ type QuestionStatusType = "correct" | "incorrect" | "skipped";
144
+ declare const useQuestions: ({ includeAllSections, }?: {
158
145
  includeAllSections?: boolean;
159
146
  }) => {
160
147
  getQuestionStatus: (qi: number, si: number) => AttemptStatus.ATTEMPTED | AttemptStatus.NOT_ATTEMPTED | AttemptStatus.NOT_VISITED | AttemptStatus.MARKED_FOR_REVIEW | AttemptStatus.ATTEMPTED_AND_MARKED_FOR_REVIEW;
161
148
  questionStatusMap: Record<AttemptStatus, {
162
149
  count: number;
163
150
  }>;
164
- getAnsweredQuestionStatus: (i: number, si: number) => AttemptStatus.ATTEMPTED | AttemptStatus.NOT_ATTEMPTED | AttemptStatus.NOT_VISITED;
151
+ getAnsweredQuestionStatus: (qi: number, si: number) => AttemptStatus.ATTEMPTED | AttemptStatus.NOT_ATTEMPTED | AttemptStatus.NOT_VISITED;
165
152
  areArraysEqual: (a: string[], b: string[]) => boolean;
166
- };
167
-
168
- type QuestionStatusType = "correct" | "incorrect" | "skipped";
169
- declare const useTestSolutionBody: () => {
170
- correctAnswer: string;
171
- currentAnswerMarks: string | number;
172
153
  currentQuestionStatus: QuestionStatusType;
154
+ currentAnswerMarks: string | number;
155
+ correctAnswer: string;
173
156
  };
174
157
 
175
- declare const useTestTimer: () => {
158
+ declare const useQuestionTimer: () => {
176
159
  timer: number;
177
160
  };
178
161
 
179
- declare const useQuestionStopWatch: (type?: "web" | "app") => {
180
- questionStopWatch: number;
162
+ declare const useTestActions: () => {
163
+ isQuizAnswer: boolean;
164
+ handleClearResponse: () => void;
165
+ handleSelectOption: (optionId: string) => void;
166
+ handleIntegerInputChange: (val: string) => void;
167
+ handleMarkForReview: () => void;
168
+ handleNext: () => void;
169
+ handlePrevious: () => void;
170
+ handleSaveAnswer: () => void;
171
+ isLastQuestion: boolean;
172
+ isFirstQuestion: boolean;
181
173
  };
182
174
 
183
- export { AttemptStatus, type SubmitTest, TestEngineProvider, useQuestionStopWatch, useTestEngine, useTestEngineBody, useTestEngineFooter, useTestQuestionStatus, useTestSolutionBody, useTestTimer };
175
+ interface SubmitTest {
176
+ payload: Record<string, any>;
177
+ pause: boolean;
178
+ autoSubmit: boolean;
179
+ }
180
+
181
+ interface ProviderRef {
182
+ reset: () => void;
183
+ }
184
+ declare const Provider: React.ForwardRefExoticComponent<{
185
+ test: Test;
186
+ isSolution?: boolean;
187
+ submitTest: React.Dispatch<SubmitTest>;
188
+ children: React.ReactNode;
189
+ } & React.RefAttributes<ProviderRef>>;
190
+
191
+ export { AttemptStatus, type ProviderRef, type SubmitTest, Provider as TestEngineProvider, useQuestionTimer, useQuestions, useTestActions, useTestEngine, useTestTimer };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,22 @@
1
- import React, { PropsWithChildren } from 'react';
1
+ import React from 'react';
2
+
3
+ declare enum AttemptStatus {
4
+ ATTEMPTED = "ATTEMPTED",
5
+ NOT_ATTEMPTED = "NOT_ATTEMPTED",
6
+ NOT_VISITED = "NOT_VISITED",
7
+ MARKED_FOR_REVIEW = "MARKED_FOR_REVIEW",
8
+ ATTEMPTED_AND_MARKED_FOR_REVIEW = "ATTEMPTED_AND_MARKED_FOR_REVIEW",
9
+ ACITVE_QUESTION = "ACITVE_QUESTION"
10
+ }
11
+ interface UserSettings {
12
+ selectedFilter?: AttemptStatus;
13
+ }
14
+ interface SolutionDetails$1 {
15
+ markedSolution?: string[];
16
+ markedForReview?: boolean;
17
+ timeTaken?: number;
18
+ isSaved?: boolean;
19
+ }
2
20
 
3
21
  declare enum TestType {
4
22
  QUIZ = "QUIZ",
@@ -21,6 +39,10 @@ declare enum TestStatus {
21
39
  NOT_STARTED = "NotStarted",
22
40
  ENDED = "Ended"
23
41
  }
42
+ declare enum ProctoringType {
43
+ BASIC = "basic",
44
+ AI = "ai"
45
+ }
24
46
  interface Test {
25
47
  name: string;
26
48
  type: TestType;
@@ -46,6 +68,8 @@ interface Test {
46
68
  status: TestStatus;
47
69
  lastVisitedQuestionId: string;
48
70
  timeTaken: Record<string, any>;
71
+ publishedAt: Date;
72
+ proctoring: ProctoringType;
49
73
  }
50
74
  interface Section {
51
75
  name: string;
@@ -73,9 +97,10 @@ interface Question {
73
97
  solutionDescription?: string;
74
98
  displayOrder: number;
75
99
  duration: number;
76
- questionResponse: SolutionDetails$1;
100
+ questionResponse: SolutionDetails;
101
+ imageUrl: string;
77
102
  }
78
- interface SolutionDetails$1 {
103
+ interface SolutionDetails {
79
104
  markedSolution?: string[];
80
105
  markedForReview?: boolean;
81
106
  timeTaken?: number;
@@ -85,99 +110,82 @@ interface Option {
85
110
  _id: string;
86
111
  }
87
112
 
88
- declare enum AttemptStatus {
89
- ATTEMPTED = "ATTEMPTED",
90
- NOT_ATTEMPTED = "NOT_ATTEMPTED",
91
- NOT_VISITED = "NOT_VISITED",
92
- MARKED_FOR_REVIEW = "MARKED_FOR_REVIEW",
93
- ATTEMPTED_AND_MARKED_FOR_REVIEW = "ATTEMPTED_AND_MARKED_FOR_REVIEW",
94
- ACITVE_QUESTION = "ACITVE_QUESTION"
95
- }
96
- interface UserSettings {
97
- selectedFilter?: AttemptStatus;
98
- }
99
- interface SolutionDetails {
100
- markedSolution?: string[];
101
- markedForReview?: boolean;
102
- timeTaken?: number;
103
- isSaved?: boolean;
104
- }
105
- interface SubmitTest {
106
- payload: Record<string, any>;
107
- pause: boolean;
108
- autoSubmit: boolean;
109
- }
110
-
111
- declare const TestEngineProvider: ({ test, submitTest, ...props }: {
112
- test: Test;
113
- isSolution?: boolean;
114
- submitTest: React.Dispatch<SubmitTest>;
115
- } & PropsWithChildren) => React.JSX.Element;
116
-
117
113
  declare const useTestEngine: () => {
118
- currentSection: Section | undefined;
119
- currentQuestion: Question | undefined;
120
- handleSubmitTest: (pause?: boolean, autoSubmit?: boolean) => Promise<Record<string, any>>;
121
- handleUpdateTestDetails: (value: Test) => void;
122
- handleUpdateQuestionCoordinates: (value: {
123
- currentQuestionIndex: number;
124
- currentSectionIndex: number;
125
- }) => Promise<void>;
126
- handleUpdateSolutions: (value: Record<string, SolutionDetails>) => void;
127
- handleUpdateCurrentAnswer: (value: SolutionDetails) => void;
128
- handleUpdateUserSettings: (value: UserSettings) => void;
129
- handleResetLocal: () => Promise<void>;
130
114
  test: Test | undefined;
131
- solutions: Record<string, SolutionDetails>;
115
+ solutions: Record<string, SolutionDetails$1>;
132
116
  currentQuestionIndex: number;
133
117
  currentSectionIndex: number;
134
- currentQuestionAnswer: SolutionDetails | undefined;
118
+ currentQuestionAnswer: SolutionDetails$1 | undefined;
135
119
  userSettings: UserSettings | undefined;
136
120
  isSolution?: boolean;
137
121
  submitting?: boolean;
122
+ timer: Record<string, number>;
123
+ isHydrated: boolean;
124
+ setTest: (test: Test, shouldUpdateSolution: boolean) => void;
125
+ setQuestionCoordinates: (sectionIndex: number, questionIndex: number) => void;
126
+ setSolution: (questionId: string, details: SolutionDetails$1) => void;
127
+ setCurrentAnswer: (answer: SolutionDetails$1 | undefined) => void;
128
+ setUserSettings: (settings: UserSettings) => void;
129
+ setTestSubmitting: (submitting: boolean) => void;
130
+ incrementTimer: (quesId: string) => void;
131
+ decrementTimer: (testId: string) => void;
132
+ reset: () => void;
133
+ setIsHydrated: (isHydrated: boolean) => void;
134
+ handleSubmitTest: (pause?: boolean, autoSubmit?: boolean) => Record<string, any>;
135
+ currentSection: Section | undefined;
136
+ currentQuestion: Question | undefined;
138
137
  };
139
138
 
140
- declare const useTestEngineBody: () => {
141
- isQuizAnswer: boolean;
142
- handleClearResponse: () => void;
143
- handleSelectOption: (optionId: string) => void;
144
- handleIntegerInputChange: (val: string) => void;
145
- handleMarkForReview: () => void;
146
- };
147
-
148
- declare const useTestEngineFooter: () => {
149
- handleNext: () => void;
150
- handlePrevious: () => void;
151
- handleSaveAnswer: () => void;
152
- handleMarkForReview: () => void;
153
- isLastQuestion: boolean;
154
- isFirstQuestion: boolean;
139
+ declare const useTestTimer: () => {
140
+ timer: number;
155
141
  };
156
142
 
157
- declare const useTestQuestionStatus: ({ includeAllSections, }?: {
143
+ type QuestionStatusType = "correct" | "incorrect" | "skipped";
144
+ declare const useQuestions: ({ includeAllSections, }?: {
158
145
  includeAllSections?: boolean;
159
146
  }) => {
160
147
  getQuestionStatus: (qi: number, si: number) => AttemptStatus.ATTEMPTED | AttemptStatus.NOT_ATTEMPTED | AttemptStatus.NOT_VISITED | AttemptStatus.MARKED_FOR_REVIEW | AttemptStatus.ATTEMPTED_AND_MARKED_FOR_REVIEW;
161
148
  questionStatusMap: Record<AttemptStatus, {
162
149
  count: number;
163
150
  }>;
164
- getAnsweredQuestionStatus: (i: number, si: number) => AttemptStatus.ATTEMPTED | AttemptStatus.NOT_ATTEMPTED | AttemptStatus.NOT_VISITED;
151
+ getAnsweredQuestionStatus: (qi: number, si: number) => AttemptStatus.ATTEMPTED | AttemptStatus.NOT_ATTEMPTED | AttemptStatus.NOT_VISITED;
165
152
  areArraysEqual: (a: string[], b: string[]) => boolean;
166
- };
167
-
168
- type QuestionStatusType = "correct" | "incorrect" | "skipped";
169
- declare const useTestSolutionBody: () => {
170
- correctAnswer: string;
171
- currentAnswerMarks: string | number;
172
153
  currentQuestionStatus: QuestionStatusType;
154
+ currentAnswerMarks: string | number;
155
+ correctAnswer: string;
173
156
  };
174
157
 
175
- declare const useTestTimer: () => {
158
+ declare const useQuestionTimer: () => {
176
159
  timer: number;
177
160
  };
178
161
 
179
- declare const useQuestionStopWatch: (type?: "web" | "app") => {
180
- questionStopWatch: number;
162
+ declare const useTestActions: () => {
163
+ isQuizAnswer: boolean;
164
+ handleClearResponse: () => void;
165
+ handleSelectOption: (optionId: string) => void;
166
+ handleIntegerInputChange: (val: string) => void;
167
+ handleMarkForReview: () => void;
168
+ handleNext: () => void;
169
+ handlePrevious: () => void;
170
+ handleSaveAnswer: () => void;
171
+ isLastQuestion: boolean;
172
+ isFirstQuestion: boolean;
181
173
  };
182
174
 
183
- export { AttemptStatus, type SubmitTest, TestEngineProvider, useQuestionStopWatch, useTestEngine, useTestEngineBody, useTestEngineFooter, useTestQuestionStatus, useTestSolutionBody, useTestTimer };
175
+ interface SubmitTest {
176
+ payload: Record<string, any>;
177
+ pause: boolean;
178
+ autoSubmit: boolean;
179
+ }
180
+
181
+ interface ProviderRef {
182
+ reset: () => void;
183
+ }
184
+ declare const Provider: React.ForwardRefExoticComponent<{
185
+ test: Test;
186
+ isSolution?: boolean;
187
+ submitTest: React.Dispatch<SubmitTest>;
188
+ children: React.ReactNode;
189
+ } & React.RefAttributes<ProviderRef>>;
190
+
191
+ export { AttemptStatus, type ProviderRef, type SubmitTest, Provider as TestEngineProvider, useQuestionTimer, useQuestions, useTestActions, useTestEngine, useTestTimer };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var ne=Object.create;var L=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var ie=Object.getPrototypeOf,oe=Object.prototype.hasOwnProperty;var ue=(n,e)=>{for(var t in e)L(n,t,{get:e[t],enumerable:!0})},G=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of re(e))!oe.call(n,s)&&s!==t&&L(n,s,{get:()=>e[s],enumerable:!(r=se(e,s))||r.enumerable});return n};var k=(n,e,t)=>(t=n!=null?ne(ie(n)):{},G(e||!n||!n.__esModule?L(t,"default",{value:n,enumerable:!0}):t,n)),ae=n=>G(L({},"__esModule",{value:!0}),n);var Ae={};ue(Ae,{AttemptStatus:()=>w,TestEngineProvider:()=>z,useQuestionStopWatch:()=>te,useTestEngine:()=>D,useTestEngineBody:()=>$,useTestEngineFooter:()=>j,useTestQuestionStatus:()=>Q,useTestSolutionBody:()=>X,useTestTimer:()=>ee});module.exports=ae(Ae);var Z=require("react");var B=k(require("react")),w=(i=>(i.ATTEMPTED="ATTEMPTED",i.NOT_ATTEMPTED="NOT_ATTEMPTED",i.NOT_VISITED="NOT_VISITED",i.MARKED_FOR_REVIEW="MARKED_FOR_REVIEW",i.ATTEMPTED_AND_MARKED_FOR_REVIEW="ATTEMPTED_AND_MARKED_FOR_REVIEW",i.ACITVE_QUESTION="ACITVE_QUESTION",i))(w||{});var q={test:void 0,solutions:{},currentQuestionIndex:0,currentSectionIndex:0,currentQuestionAnswer:{},userSettings:{},isSolution:!1,submitting:!1},C=B.default.createContext([q,()=>{},()=>{}]);C.displayName="TestEngineContext";var K=(n,e)=>{switch(e.type){case"UPDATE_TEST":return{...n,test:e.value};case"UPDATE_SOLUTIONS":return{...n,solutions:e.value};case"UPDATE_CURRENT_ANSWER":return{...n,currentQuestionAnswer:e.value};case"UPDATE_USER_SETTINGS":return{...n,userSettings:e.value};case"UPDATE_TEST_SUBMITTING":return{...n,submitting:e.value};case"UPDATE_QUESTION_COORDINATES":return{...n,currentSectionIndex:e.value.currentSectionIndex,currentQuestionIndex:e.value.currentQuestionIndex}}};var y=k(require("react"));var J=require("react-native-mmkv"),ce=()=>{if(!(typeof navigator<"u"&&navigator.product==="ReactNative")&&typeof window<"u"&&window.localStorage)return{getItem:e=>localStorage.getItem(e)?JSON.parse(localStorage.getItem(e)):null,setItem:(e,t)=>localStorage.setItem(e,JSON.stringify(t)),removeItem:e=>localStorage.removeItem(e)};{let e=new J.MMKV({id:"testforce-engine"});return{getItem:t=>{try{let r=e.getString(t);return r?JSON.parse(r):null}catch(r){return console.log(r),null}},setItem:(t,r)=>{try{e.set(t,JSON.stringify(r))}catch(s){console.log(s)}},removeItem:t=>{try{e.delete(t)}catch(r){console.log(r)}}}}},l=ce();var de=({test:n,submitTest:e,...t})=>{let[r,s]=y.default.useState(!1),[u,i]=y.default.useReducer(K,{...q,test:n,isSolution:t.isSolution}),c=async()=>{let T=await l.getItem(`${n?._id}-test-initiated`),_=await l.getItem(`${n._id}-solutions`)||{};i(T?{type:"UPDATE_SOLUTIONS",value:_}:{type:"UPDATE_SOLUTIONS",value:n?.sections?.reduce((o,S)=>(S.questions?.forEach(a=>{a.questionResponse&&(o[a._id]={...a.questionResponse})}),o),{})||{}});let d=await l.getItem(`${n._id}-currentSectionIndex`)||0,E=await l.getItem(`${n._id}-currentQuestionIndex`)||0;i({type:"UPDATE_QUESTION_COORDINATES",value:{currentSectionIndex:d,currentQuestionIndex:E}}),s(!0)};return(0,Z.useEffect)(()=>{c()},[]),r?y.default.createElement(C.Provider,{value:[u,i,e],...t}):y.default.createElement(y.default.Fragment,null)},z=de;var A=k(require("react"));var me=()=>{let n=A.default.useContext(C);if(n===void 0)throw new Error("useTestEngine must be use within TestEngineProvider");let[e,t,r]=n,s=A.default.useMemo(()=>e.test?.sections[e.currentSectionIndex],[e.currentSectionIndex]),u=A.default.useMemo(()=>s?.questions[e.currentQuestionIndex],[e.currentQuestionIndex,s]);A.default.useEffect(()=>{u&&(e.solutions[u._id]?c({...e.solutions[u._id],isSaved:!0}):(e.isSolution||o({...e.solutions,[u._id]:{}}),c({}))),l.setItem(`${e.test?._id}-currentSectionIndex`,e.currentSectionIndex),l.setItem(`${e.test?._id}-currentQuestionIndex`,e.currentQuestionIndex)},[e.currentSectionIndex,e.currentQuestionIndex]);let i=A.default.useCallback(m=>t({type:"UPDATE_TEST",value:m}),[t]),c=A.default.useCallback(m=>t({type:"UPDATE_CURRENT_ANSWER",value:m}),[t]),T=A.default.useCallback(async m=>(await _(),t({type:"UPDATE_QUESTION_COORDINATES",value:m})),[t]),_=async()=>{let m=await l.getItem(`${e?.test?._id}-timers`)||{};e.test?.sections.forEach(U=>{U.questions?.forEach(R=>{m[R._id]&&!e.solutions[R._id]&&(e.solutions[R._id]={}),e.solutions[R._id]&&(e.solutions[R._id].timeTaken=m[R._id])})})},d=A.default.useCallback(m=>t({type:"UPDATE_USER_SETTINGS",value:m}),[t]),E=A.default.useCallback(m=>t({type:"UPDATE_TEST_SUBMITTING",value:m}),[t]);A.default.useEffect(()=>{e.isSolution||l.setItem(`${e.test?._id}-solutions`,e.solutions)},[e.solutions]);let o=A.default.useCallback(m=>t({type:"UPDATE_SOLUTIONS",value:m}),[t]),S=A.default.useCallback(async()=>{if(!await l.getItem(`${e.test?._id}-test-initiated`)&&e.test?.status==="Paused"){let U=await l.getItem(`${e?.test?._id}-timers`)||{},R={};e.test?.sections?.forEach((p,g)=>{p.questions?.forEach((I,v)=>{I._id===e.test?.lastVisitedQuestionId&&T({currentSectionIndex:g,currentQuestionIndex:v}),I.questionResponse&&(R[I._id]=JSON.stringify(I.questionResponse.timeTaken||0))})}),l.setItem(`${e?.test?._id}-timers`,{...U,...R})}e?.isSolution||l.setItem(`${e.test?._id}-test-initiated`,"true")},[]);A.default.useEffect(()=>{S()},[]);let a=async()=>{await l.removeItem(`${e.test?._id}-currentQuestionIndex`),await l.removeItem(`${e.test?._id}-currentSectionIndex`),await l.removeItem(`${e.test?._id}-solutions`),await l.removeItem(`${e.test?._id}-test-initiated`),await l.removeItem(`${e?.test?._id}-timers`)},f=A.default.useCallback(async(m=!1,U=!1)=>{E(!0);let R=await l.getItem(`${e.test?._id}-solutions`)||{},p=await l.getItem(`${e?.test?._id}-timers`)||{},g=[];e.test?.sections.forEach(v=>{v.questions.forEach(P=>{let F={questionId:P._id};R[P._id]&&(F.markedSolution=R[P._id].markedSolution||[],F.timeTaken=parseInt(p[P._id]||0),F.markedForReview=R[P._id].markedForReview||!1,g.push(F))})});let I={submittedBy:U?"autoSubmit":"user",questionResponses:g,testMappingId:e.test?.testMappingId,type:m?"Pause":"Submit",testId:e.test?._id};return m&&(I.lastVisitedQuestionId=u?._id),e.test?.timerLevel==="TEST"&&e.test.type==="TEST"&&m&&p[e?.test?._id]&&(I.timeTaken={[e.test?._id]:p[e?.test?._id]}),g.length||delete I.questionResponses,await a(),E(!1),r({payload:I,pause:m,autoSubmit:U}),I},[u]);return A.default.useMemo(()=>({...e,currentSection:s,currentQuestion:u,handleSubmitTest:f,handleUpdateTestDetails:i,handleUpdateQuestionCoordinates:T,handleUpdateSolutions:o,handleUpdateCurrentAnswer:c,handleUpdateUserSettings:d,handleResetLocal:a}),[e,s,u,f,i,T,o,c,d,a])},D=me;var N=k(require("react"));var Ee=()=>{let{currentQuestion:n,currentQuestionAnswer:e,test:t,solutions:r,isSolution:s,handleUpdateCurrentAnswer:u,handleUpdateSolutions:i}=D(),c=N.default.useMemo(()=>t?.type==="QUIZ"&&!!r[n?._id]?.markedSolution?.length,[t,r,n]),T=(0,N.useCallback)(()=>{u({...e,markedSolution:[],isSaved:!1}),i({...r,[n?._id]:{...e,markedSolution:[]}})},[e,n,r,u,i]),_=(0,N.useCallback)(o=>{if(!(s||c))if(e?.markedSolution?.includes(o)){let S=e.markedSolution.filter(a=>a!==o);return S?.length===0?T():u({...e,markedSolution:S,isSaved:!1})}else{if(n?.type==="SINGLE")return u({...e,markedSolution:[o],isSaved:!1});{let S=e?.markedSolution?.length?e?.markedSolution:[];return u({...e,markedSolution:[...S,o],isSaved:!1})}}},[s,c,n,e,u,T]),d=(0,N.useCallback)(o=>{s||c||(u({...e,markedSolution:o?[o]:[],isSaved:!1}),o||T())},[s,c,u,e,T]),E=(0,N.useCallback)(()=>{u({...e,markedForReview:!e?.markedForReview}),i({...r,[n._id]:{...r[n._id],markedForReview:!e?.markedForReview}})},[u,i,e,r,n]);return{isQuizAnswer:c,handleClearResponse:T,handleSelectOption:_,handleIntegerInputChange:d,handleMarkForReview:E}},$=Ee;var O=require("react");var W=k(require("react"));var fe=({includeAllSections:n}={})=>{let{currentQuestionIndex:e,solutions:t,currentSectionIndex:r,test:s,isSolution:u}=D(),[i,c]=W.default.useState({MARKED_FOR_REVIEW:{count:0},ATTEMPTED:{count:0},ATTEMPTED_AND_MARKED_FOR_REVIEW:{count:0},NOT_ATTEMPTED:{count:0},NOT_VISITED:{count:0},ACITVE_QUESTION:{count:0}}),T=()=>{let o={...i};Object.values(o).forEach(S=>S.count=0),n?s?.sections?.forEach((S,a)=>{S?.questions?.forEach((f,b)=>{let m=u||s.type==="QUIZ"?E(b,a):_(b,a);o[m].count+=1})}):s?.sections[r]?.questions.forEach((S,a)=>{let f=u||s.type==="QUIZ"?E(a,r):_(a,r);o[f].count+=1}),c(o)};W.default.useEffect(()=>{T()},[e,t,r]);let _=(o,S)=>{let a=s?.sections[S]?.questions[o],f;return t[a?._id]&&t[a?._id].markedSolution?.length&&t[a?._id].markedForReview?f="ATTEMPTED_AND_MARKED_FOR_REVIEW":t[a?._id]&&t[a?._id].markedForReview?f="MARKED_FOR_REVIEW":t[a?._id]&&t[a?._id].markedSolution?.length?f="ATTEMPTED":t[a?._id]?f="NOT_ATTEMPTED":f="NOT_VISITED",f};function d(o,S){let a=o.slice().sort(),f=S.slice().sort();if(a.length!==f.length)return!1;for(let b=0;b<a.length;b++)if(a[b]!==f[b])return!1;return!0}let E=(o,S)=>{let a=s?.sections[S]?.questions[o],f;return t[a?._id]&&t[a?._id].markedSolution?.length?d(t[a?._id].markedSolution,a.solution)?f="ATTEMPTED":f="NOT_ATTEMPTED":f="NOT_VISITED",f};return{getQuestionStatus:_,questionStatusMap:i,getAnsweredQuestionStatus:E,areArraysEqual:d}},Q=fe;var Ie=()=>{let{handleUpdateQuestionCoordinates:n,currentQuestionIndex:e,currentSectionIndex:t,currentSection:r,currentQuestionAnswer:s,handleUpdateSolutions:u,solutions:i,currentQuestion:c,handleUpdateCurrentAnswer:T,test:_,userSettings:d}=D(),{getAnsweredQuestionStatus:E}=Q(),[o,S]=(0,O.useState)([]);(0,O.useEffect)(()=>{if(d?.selectedFilter){let p=r?.questions?.map((g,I)=>{if(d?.selectedFilter===E(I,t))return I})?.filter(g=>g!==void 0);S(p),p?.length&&n({currentSectionIndex:t,currentQuestionIndex:p[0]||0})}else S([])},[d?.selectedFilter,r]);let a=()=>{s?.isSaved||(delete s?.isSaved,u({...i,[c?._id]:{...s}}))},f=()=>{if(d?.selectedFilter){let I=o?.findIndex(v=>v===e);I>=0&&o[I+1]>=0&&n({currentSectionIndex:t,currentQuestionIndex:o[I+1]});return}let p=r?.questions[e+1]?t:_?.sections[t+1]?t+1:t,g=r?.questions[e+1]?e+1:0;n({currentSectionIndex:p,currentQuestionIndex:g})},b=()=>{if(d?.selectedFilter){let I=o?.findIndex(v=>v===e);I>=0&&o[I-1]>=0&&n({currentSectionIndex:t,currentQuestionIndex:o[I-1]});return}let p=r?.questions[e-1]?t:_?.sections[t-1]?t-1:t,g=r?.questions[e-1]?e-1:_.sections[p]?.questions?.length-1;n({currentSectionIndex:p,currentQuestionIndex:g})},m=(0,O.useMemo)(()=>{if(d?.selectedFilter){let p=o?.findIndex(g=>g===e);return!o[p+1]}return!_?.sections[t+1]&&!r?.questions[e+1]},[t,e,o,d?.selectedFilter]),U=(0,O.useMemo)(()=>d?.selectedFilter?o?.findIndex(g=>g===e)<=0:t===0&&e===0,[t,e,o,d?.selectedFilter]);return{handleNext:f,handlePrevious:b,handleSaveAnswer:a,handleMarkForReview:()=>{T({...s,markedForReview:!s?.markedForReview}),u({...i,[c._id]:{...i[c._id],markedForReview:!s?.markedForReview}})},isLastQuestion:m,isFirstQuestion:U}},j=Ie;var V=k(require("react"));var H={1:{label:"A"},2:{label:"B"},3:{label:"C"},4:{label:"D"}},_e=()=>{let{currentQuestionIndex:n,test:e,currentSection:t,currentSectionIndex:r,currentQuestion:s}=D(),{getAnsweredQuestionStatus:u}=Q(),i=V.default.useMemo(()=>u(n,r)==="ATTEMPTED"?"correct":u(n,r)==="NOT_ATTEMPTED"?"incorrect":"skipped",[n,r]),c=V.default.useMemo(()=>{switch(i){case"correct":return e?.marksLevel==="TEST"?"+"+e.positiveMarks:"+"+t?.positiveMarks;case"incorrect":return e?.marksLevel==="TEST"?e.isNegativeMarkingEnabled?"-"+e.negativeMarks:0:t?.isNegativeMarkingEnabled?"-"+t?.negativeMarks:0;case"skipped":return 0}},[i,r,n]);return{correctAnswer:V.default.useMemo(()=>{if(!s)return"";if(s.type==="INTEGER")return s.solution[0];if(s.type==="SINGLE"){let _=s.options.findIndex(d=>d._id===s.solution[0]);return H[_+1]?.label||""}return s.type==="MULTIPLE"?s.solution.map(d=>{let E=s.options.findIndex(o=>o._id===d);return H[E+1]?.label||""}).join(", "):""},[s]),currentAnswerMarks:c,currentQuestionStatus:i}},X=_e;var M=k(require("react"));var pe=()=>{let{test:n,handleSubmitTest:e}=D(),t=M.default.useRef(null),[r,s]=M.default.useState(n?.timeTaken?.[n?._id]??n?.duration??0),u=M.default.useCallback(async c=>{t.current&&clearTimeout(t.current);let T=await l.getItem(`${n?._id}-timers`);if(c<=0){e(!1,!0);return}T[n._id]=c+"",l.setItem(`${n?._id}-timers`,T),s(c),t.current=setTimeout(()=>{u(c-1)},1e3)},[n,e]),i=M.default.useCallback(async()=>{if(!n?._id)return;let c=await l.getItem(`${n._id}-timers`);c||(await l.setItem(`${n._id}-timers`,{}),c={});let T=parseInt(c?.[n._id]||n?.timeTaken?.[n._id]||n?.duration||0);u(T)},[n,u]);return M.default.useEffect(()=>(i(),()=>{t.current&&clearTimeout(t.current)}),[i,n?._id]),{timer:r}},ee=pe;var h=k(require("react"));var ge=n=>{let e=n==="app"?950:1e3,{currentQuestion:t,solutions:r,test:s}=D(),{isQuizAnswer:u}=$(),i=h.default.useRef(null),[c,T]=h.default.useState(0),_=async E=>{if(!t)return;let o=await l.getItem(`${s?._id}-timers`);if((r[t?._id]?.markedSolution||[])?.length===0)o[t?._id]=E+"",l.setItem(`${s?._id}-timers`,o),T(E);else{clearTimeout(i.current);return}i.current=setTimeout(()=>{_(E+1)},e)},d=async()=>{i.current&&(clearTimeout(i.current),i.current=null);let E=await l.getItem(`${s?._id}-timers`);E||(await l.setItem(`${s?._id}-timers`,{}),E={});let o=parseInt(E?.[t?._id]||s?.timeTaken?.[t?._id]||0);T(o),_(o)};return h.default.useEffect(()=>(t?._id&&d(),()=>{i.current&&(clearTimeout(i.current),i.current=null)}),[t]),h.default.useEffect(()=>{i.current===null&&setTimeout(()=>{i.current===null&&d()},e)},[r]),h.default.useEffect(()=>{u&&(clearTimeout(i.current),i.current=null)},[u]),{questionStopWatch:c}},te=ge;0&&(module.exports={AttemptStatus,TestEngineProvider,useQuestionStopWatch,useTestEngine,useTestEngineBody,useTestEngineFooter,useTestQuestionStatus,useTestSolutionBody,useTestTimer});
1
+ "use strict";var re=Object.create;var P=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ie=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty;var ae=(t,e)=>{for(var n in e)P(t,n,{get:e[n],enumerable:!0})},z=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of oe(e))!ue.call(t,o)&&o!==n&&P(t,o,{get:()=>e[o],enumerable:!(s=se(e,o))||s.enumerable});return t};var O=(t,e,n)=>(n=t!=null?re(ie(t)):{},z(e||!t||!t.__esModule?P(n,"default",{value:t,enumerable:!0}):n,t)),ce=t=>z(P({},"__esModule",{value:!0}),t);var _e={};ae(_e,{AttemptStatus:()=>V,TestEngineProvider:()=>ee,useQuestionTimer:()=>J,useQuestions:()=>U,useTestActions:()=>X,useTestEngine:()=>k,useTestTimer:()=>Y});module.exports=ce(_e);var F=O(require("react"));var B=require("zustand"),C=require("zustand/middleware");var de=()=>typeof globalThis>"u"||!globalThis.localStorage?null:{setItem:(t,e)=>{globalThis.localStorage.setItem(t,e)},getItem:t=>globalThis.localStorage.getItem(t)??null,removeItem:t=>{globalThis.localStorage.removeItem(t)}},le=()=>{try{let{createMMKV:t}=require("react-native-mmkv"),e=t();return{setItem:(n,s)=>{e.set(n,s)},getItem:n=>e.getString(n)??null,removeItem:n=>{e.delete(n)}}}catch{return null}},K={},me=()=>({setItem:(t,e)=>{K[t]=e},getItem:t=>K[t]??null,removeItem:t=>{delete K[t]}}),h=de()||le()||me();var Z=O(require("react")),W={test:void 0,solutions:{},currentQuestionIndex:0,currentSectionIndex:0,currentQuestionAnswer:{},userSettings:{},isSolution:!1,submitting:!1,timer:{},isHydrated:!1},w=Z.default.createContext([W,()=>{}]);w.displayName="TestEngineContext";var i=(0,B.create)()((0,C.persist)(t=>({...W,setQuestionCoordinates:(e,n)=>t(s=>{let r=s.test?.sections[e]?.questions[n]?._id,c=null;return s.isSolution||(s.solutions[r]?c={...s.solutions,[r]:{...s.solutions[r],timeTaken:s.timer[r]||0}}:c={...s.solutions,[r]:{}}),{currentSectionIndex:e,currentQuestionIndex:n,currentQuestionAnswer:c?.[r]||{},...c&&{solutions:c}}}),setTest:(e,n)=>t(()=>{if(!n)return{test:e};let s={},o={},u=0,r=0;e?.sections?.forEach((E,p)=>{E?.questions?.forEach((T,A)=>{T?.questionResponse&&(s={...s,[T?._id]:{markedSolution:T?.questionResponse?.markedSolution||[],markedForReview:T?.questionResponse?.markedForReview||!1,timeTaken:T?.questionResponse?.timeTaken||0,isSaved:!0}},o={...o,[T?._id]:T?.questionResponse?.timeTaken||0}),e?.status==="Paused"&&T._id===e?.lastVisitedQuestionId&&(u=p,r=A)})}),o[e?._id]=e?.timeTaken&&+e?.timeTaken[e?._id]||+e?.duration||0;let c=e?.sections[u]?.questions[r]?._id,m=s[c]||{};return{test:e,solutions:s,timer:o,currentSectionIndex:u,currentQuestionIndex:r,currentQuestionAnswer:m}}),setSolution:(e,n)=>t(s=>({solutions:{...s.solutions,[e]:{...s.solutions[e],...n}},currentQuestionAnswer:{...s.solutions[e],...n}})),incrementTimer:e=>t(n=>({timer:{...n.timer,[e]:(n.timer[e]||0)+1}})),decrementTimer:e=>t(n=>({timer:{...n.timer,[e]:(n.timer[e]||0)-1}})),setCurrentAnswer:e=>t({currentQuestionAnswer:e}),setUserSettings:e=>t({userSettings:e}),setTestSubmitting:e=>t({submitting:e}),reset:()=>t(W),setIsHydrated:e=>t({isHydrated:e})}),{name:"test-engine-v2-store",storage:(0,C.createJSONStorage)(()=>h)}));var Te=()=>{let t=F.default.useContext(w);if(t===void 0)throw new Error("useTestEngineV2 must be use within TestEngineProvider");let[e,n]=t;if(!e.test)throw new Error("Please provide test data to useTestEngineV2");let s=i(S=>S.test),o=i(S=>S.setTestSubmitting),u=i(S=>S.solutions),r=i(S=>S.currentQuestionIndex),c=i(S=>S.currentSectionIndex),m=(0,F.useMemo)(()=>s?.sections[c],[s,c]),E=(0,F.useMemo)(()=>m?.questions[r],[m,r]),p=i(S=>S.reset),T=i(S=>S.timer);return{handleSubmitTest:(S=!1,_=!1)=>{o(!0);let x=[];s?.sections?.forEach(f=>{f?.questions?.forEach(d=>{u[d._id]&&x.push({questionId:d._id,markedSolution:u[d._id]?.isSaved?u[d._id]?.markedSolution:[],timeTaken:T[d._id]||u[d._id]?.timeTaken||0,markedForReview:u[d._id]?.markedForReview||!1})})});let Q={submittedBy:_?"autoSubmit":"user",questionResponses:x,testMappingId:s?.testMappingId,type:S?"Pause":"Submit",testId:s?._id,...S?{lastVisitedQuestionId:E?._id}:{},...s?.type==="TEST"&&S&&T[s?._id]?{timeTaken:{[s?._id]:T[s?._id]}}:{}};return x.length||delete Q.questionResponses,o(!1),n({payload:Q,pause:S,autoSubmit:_}),Q},currentSection:m,currentQuestion:E,...i.getState(),...e}},k=Te;var N=require("react");var Se=()=>{let{isSolution:t,handleSubmitTest:e}=k(),n=i(m=>m.test),s=i(m=>m.timer),o=i(m=>m.decrementTimer),u=i(m=>m.isHydrated),r=(0,N.useRef)(null),c=()=>{n&&u&&o(n?._id),r.current=setTimeout(()=>{c()},1e3)};return(0,N.useEffect)(()=>{if(n&&s[n?._id]<=0){clearTimeout(r.current),e(!1,!0);return}},[s,n]),(0,N.useEffect)(()=>{if(!t)return c(),()=>{r.current&&clearTimeout(r.current)}},[n,u]),{timer:s[n._id]||0}},Y=Se;var M=O(require("react"));var V=(r=>(r.ATTEMPTED="ATTEMPTED",r.NOT_ATTEMPTED="NOT_ATTEMPTED",r.NOT_VISITED="NOT_VISITED",r.MARKED_FOR_REVIEW="MARKED_FOR_REVIEW",r.ATTEMPTED_AND_MARKED_FOR_REVIEW="ATTEMPTED_AND_MARKED_FOR_REVIEW",r.ACITVE_QUESTION="ACITVE_QUESTION",r))(V||{});var j={1:{label:"A"},2:{label:"B"},3:{label:"C"},4:{label:"D"}},ge=({includeAllSections:t}={})=>{let e=i(f=>f.test),n=i(f=>f.solutions),s=i(f=>f.isSolution),o=i(f=>f.currentSectionIndex),{currentQuestion:u,currentSection:r}=k(),c=i(f=>f.currentQuestionIndex),[m,E]=M.default.useState({MARKED_FOR_REVIEW:{count:0},ATTEMPTED:{count:0},ATTEMPTED_AND_MARKED_FOR_REVIEW:{count:0},NOT_ATTEMPTED:{count:0},NOT_VISITED:{count:0},ACITVE_QUESTION:{count:0}}),p=(0,M.useCallback)((f,d)=>{let a=e?.sections[d]?.questions[f],g=n[a?._id];return g?g?.markedSolution&&g?.markedSolution?.length>0&&g?.markedForReview?"ATTEMPTED_AND_MARKED_FOR_REVIEW":g?.markedSolution&&g?.markedSolution?.length>0?"ATTEMPTED":g?.markedForReview?"MARKED_FOR_REVIEW":"NOT_ATTEMPTED":"NOT_VISITED"},[n,e]),T=(0,M.useCallback)((f,d)=>{let a=e?.sections[d]?.questions[f],g=n[a?._id];return g?.markedSolution?.length?S(g.markedSolution,a.solution)?"ATTEMPTED":"NOT_ATTEMPTED":"NOT_VISITED"},[n,e]),A=(0,M.useCallback)(()=>{let f={...m};Object.values(f).forEach(d=>d.count=0),t?e?.sections?.forEach((d,a)=>{d?.questions?.forEach((g,D)=>{let H=s||e.type==="QUIZ"?T(D,a):p(D,a);f[H].count+=1})}):e?.sections[o]?.questions.forEach((d,a)=>{let g=s||e.type==="QUIZ"?T(a,o):p(a,o);f[g].count+=1}),E(f)},[T,p,t,s,e,o,n]);M.default.useEffect(()=>{A()},[c,n,o]);function S(f,d){let a=f.slice().sort(),g=d.slice().sort();if(a.length!==g.length)return!1;for(let D=0;D<a.length;D++)if(a[D]!==g[D])return!1;return!0}let _=M.default.useMemo(()=>T(c,o)==="ATTEMPTED"?"correct":T(c,o)==="NOT_ATTEMPTED"?"incorrect":"skipped",[c,o,T]),x=M.default.useMemo(()=>{switch(_){case"correct":return e?.marksLevel==="TEST"?"+"+e.positiveMarks:"+"+r?.positiveMarks;case"incorrect":return e?.marksLevel==="TEST"?e.isNegativeMarkingEnabled?"-"+e.negativeMarks:0:r?.isNegativeMarkingEnabled?"-"+r?.negativeMarks:0;case"skipped":return 0}},[_]),Q=M.default.useMemo(()=>{if(!u)return"";if(u.type==="INTEGER")return u.solution[0];if(u.type==="SINGLE"){let f=u.options.findIndex(d=>d._id===u.solution[0]);return j[f+1]?.label||""}return u.type==="MULTIPLE"?u.solution.map(d=>{let a=u.options.findIndex(g=>g._id===d);return j[a+1]?.label||""}).join(", "):""},[u]);return{getQuestionStatus:p,questionStatusMap:m,getAnsweredQuestionStatus:T,areArraysEqual:S,currentQuestionStatus:_,currentAnswerMarks:x,correctAnswer:Q}},U=ge;var q=require("react");var Ee=()=>{let{currentQuestion:t,isSolution:e}=k(),n=i(m=>m.timer),s=i(m=>m.incrementTimer),o=i(m=>m.solutions),u=i(m=>m.isHydrated),r=(0,q.useRef)(null),c=()=>{t&&!o[t?._id]?.markedSolution?.length&&u&&s(t?._id),r.current=setTimeout(()=>{c()},1e3)};return(0,q.useEffect)(()=>{if(!e)return c(),()=>{r.current&&clearTimeout(r.current)}},[t,o,u]),{timer:n[t._id]||0}},J=Ee;var I=O(require("react"));var pe=()=>{let t=i(l=>l.test),e=i(l=>l.solutions),{currentQuestion:n,currentSection:s,currentQuestionAnswer:o}=k(),u=i(l=>l.currentQuestionIndex),r=i(l=>l.currentSectionIndex),c=i(l=>l.userSettings),m=i(l=>l.isSolution),E=i(l=>l.setQuestionCoordinates),p=i(l=>l.setSolution),T=i(l=>l.setCurrentAnswer),{getAnsweredQuestionStatus:A}=U(),S=I.default.useMemo(()=>t?.type==="QUIZ"&&!!e[n?._id]?.markedSolution?.length,[t,e,n]),_=(0,I.useCallback)(()=>{T({...o,markedSolution:[],isSaved:!1}),p(n?._id,{...o,markedSolution:[]})},[o,n,p]),x=(0,I.useCallback)(l=>{if(!(m||S))if(o?.markedSolution?.includes(l)){let b=o.markedSolution.filter(R=>R!==l);if(b?.length===0)return _();T({...o,markedSolution:b,isSaved:!1});return}else if(n?.type==="SINGLE"){T({...o,markedSolution:[l],isSaved:!1});return}else{let b=o?.markedSolution?.length?o?.markedSolution:[];T({...o,markedSolution:[...b,l],isSaved:!1});return}},[m,S,n,o,T,_]),Q=(0,I.useCallback)(l=>{m||S||(T({...o,markedSolution:l?[l]:[],isSaved:!1}),l||_())},[m,S,o,_]),f=(0,I.useCallback)(()=>{T({...o,markedForReview:!o?.markedForReview}),p(n._id,{...e[n._id],markedForReview:!o?.markedForReview})},[p,o,e,n]),[d,a]=(0,I.useState)([]);(0,I.useEffect)(()=>{if(c?.selectedFilter){let l=s?.questions?.map((b,R)=>{if(c?.selectedFilter===A(R,r))return R})?.filter(b=>b!==void 0);a(l),l?.length&&E(r,l[0]||0)}else a([])},[c,s,A,E]);let g=(0,I.useCallback)(()=>{o?.isSaved||p(n?._id,{...o,isSaved:!0})},[o,n,p]),D=(0,I.useCallback)(()=>{if(c?.selectedFilter){let R=d?.findIndex(L=>L===u);R>=0&&d[R+1]>=0&&E(r,d[R+1]);return}let l=s?.questions[u+1]?r:t?.sections[r+1]?r+1:r,b=s?.questions[u+1]?u+1:0;E(l,b)},[c?.selectedFilter,d,u,r,s,t,E]),H=(0,I.useCallback)(()=>{if(c?.selectedFilter){let R=d?.findIndex(L=>L===u);R>=0&&d[R-1]>=0&&E(r,d[R-1]);return}let l=s?.questions[u-1]?r:t?.sections[r-1]?r-1:r,b=s?.questions[u-1]?u-1:t.sections[l]?.questions?.length-1;E(l,b)},[c?.selectedFilter,d,u,r,s,t,E]),te=(0,I.useMemo)(()=>{if(c?.selectedFilter){let l=d?.findIndex(b=>b===u);return!d[l+1]}return!t?.sections[r+1]&&!s?.questions[u+1]},[r,u,d,c?.selectedFilter,t,s]),ne=(0,I.useMemo)(()=>c?.selectedFilter?d?.findIndex(b=>b===u)<=0:r===0&&u===0,[r,u,d,c?.selectedFilter]);return{isQuizAnswer:S,handleClearResponse:_,handleSelectOption:x,handleIntegerInputChange:Q,handleMarkForReview:f,handleNext:D,handlePrevious:H,handleSaveAnswer:g,isLastQuestion:te,isFirstQuestion:ne}},X=pe;var y=require("react"),G=O(require("react"));var Ie=(0,y.forwardRef)(({test:t,isSolution:e,submitTest:n,children:s},o)=>{let u=i(a=>a.setTest),r=i(a=>a.setIsHydrated),c=i(a=>a.isHydrated),m=i(a=>a.test),E=i(a=>a.solutions),p=i(a=>a.currentQuestionIndex),T=i(a=>a.currentSectionIndex),A=i(a=>a.currentQuestionAnswer),S=i(a=>a.userSettings),_=i(a=>a.submitting),x=i(a=>a.timer),Q=i(a=>a.reset),f=G.default.useMemo(()=>({test:m,solutions:E,currentQuestionIndex:p,currentSectionIndex:T,userSettings:S,isSolution:e||!1,submitting:_,timer:x,isHydrated:c,currentQuestionAnswer:A}),[m,E,p,T,S,e,_,x,c,A]),d=()=>{console.log("[RESET]: Called"),Q(),h.removeItem(`${t?._id}-test-initiated`),h.removeItem(`test-engine-v2-store-${t?._id}`),h.removeItem("test-engine-v2-store")};return(0,y.useImperativeHandle)(o,()=>({reset:d})),(0,y.useEffect)(()=>{(async()=>{if(!(c&&t?._id===m?._id))try{h.getItem(`${t?._id}-test-initiated`)?u(t,!1):(u(t,!0),e||h.setItem(`${t?._id}-test-initiated`,"true")),i.persist.setOptions({name:`test-engine-v2-store-${t?._id}`}),await i.persist.rehydrate(),h.removeItem("test-engine-v2-store"),r(!0)}catch(g){console.error("Error initializing test engine store:",g),r(!0)}})()},[t?._id,c,u,r]),!c||!m?null:G.default.createElement(w.Provider,{value:[f,n]},s)}),ee=Ie;0&&(module.exports={AttemptStatus,TestEngineProvider,useQuestionTimer,useQuestions,useTestActions,useTestEngine,useTestTimer});
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{useEffect as Y}from"react";import K from"react";var w=(r=>(r.ATTEMPTED="ATTEMPTED",r.NOT_ATTEMPTED="NOT_ATTEMPTED",r.NOT_VISITED="NOT_VISITED",r.MARKED_FOR_REVIEW="MARKED_FOR_REVIEW",r.ATTEMPTED_AND_MARKED_FOR_REVIEW="ATTEMPTED_AND_MARKED_FOR_REVIEW",r.ACITVE_QUESTION="ACITVE_QUESTION",r))(w||{});var F={test:void 0,solutions:{},currentQuestionIndex:0,currentSectionIndex:0,currentQuestionAnswer:{},userSettings:{},isSolution:!1,submitting:!1},O=K.createContext([F,()=>{},()=>{}]);O.displayName="TestEngineContext";var V=(n,e)=>{switch(e.type){case"UPDATE_TEST":return{...n,test:e.value};case"UPDATE_SOLUTIONS":return{...n,solutions:e.value};case"UPDATE_CURRENT_ANSWER":return{...n,currentQuestionAnswer:e.value};case"UPDATE_USER_SETTINGS":return{...n,userSettings:e.value};case"UPDATE_TEST_SUBMITTING":return{...n,submitting:e.value};case"UPDATE_QUESTION_COORDINATES":return{...n,currentSectionIndex:e.value.currentSectionIndex,currentQuestionIndex:e.value.currentQuestionIndex}}};import y from"react";import{MMKV as J}from"react-native-mmkv";var Z=()=>{if(!(typeof navigator<"u"&&navigator.product==="ReactNative")&&typeof window<"u"&&window.localStorage)return{getItem:e=>localStorage.getItem(e)?JSON.parse(localStorage.getItem(e)):null,setItem:(e,t)=>localStorage.setItem(e,JSON.stringify(t)),removeItem:e=>localStorage.removeItem(e)};{let e=new J({id:"testforce-engine"});return{getItem:t=>{try{let o=e.getString(t);return o?JSON.parse(o):null}catch(o){return console.log(o),null}},setItem:(t,o)=>{try{e.set(t,JSON.stringify(o))}catch(s){console.log(s)}},removeItem:t=>{try{e.delete(t)}catch(o){console.log(o)}}}}},l=Z();var j=({test:n,submitTest:e,...t})=>{let[o,s]=y.useState(!1),[u,r]=y.useReducer(V,{...F,test:n,isSolution:t.isSolution}),c=async()=>{let T=await l.getItem(`${n?._id}-test-initiated`),_=await l.getItem(`${n._id}-solutions`)||{};r(T?{type:"UPDATE_SOLUTIONS",value:_}:{type:"UPDATE_SOLUTIONS",value:n?.sections?.reduce((i,S)=>(S.questions?.forEach(a=>{a.questionResponse&&(i[a._id]={...a.questionResponse})}),i),{})||{}});let d=await l.getItem(`${n._id}-currentSectionIndex`)||0,E=await l.getItem(`${n._id}-currentQuestionIndex`)||0;r({type:"UPDATE_QUESTION_COORDINATES",value:{currentSectionIndex:d,currentQuestionIndex:E}}),s(!0)};return Y(()=>{c()},[]),o?y.createElement(O.Provider,{value:[u,r,e],...t}):y.createElement(y.Fragment,null)},H=j;import A from"react";var ee=()=>{let n=A.useContext(O);if(n===void 0)throw new Error("useTestEngine must be use within TestEngineProvider");let[e,t,o]=n,s=A.useMemo(()=>e.test?.sections[e.currentSectionIndex],[e.currentSectionIndex]),u=A.useMemo(()=>s?.questions[e.currentQuestionIndex],[e.currentQuestionIndex,s]);A.useEffect(()=>{u&&(e.solutions[u._id]?c({...e.solutions[u._id],isSaved:!0}):(e.isSolution||i({...e.solutions,[u._id]:{}}),c({}))),l.setItem(`${e.test?._id}-currentSectionIndex`,e.currentSectionIndex),l.setItem(`${e.test?._id}-currentQuestionIndex`,e.currentQuestionIndex)},[e.currentSectionIndex,e.currentQuestionIndex]);let r=A.useCallback(m=>t({type:"UPDATE_TEST",value:m}),[t]),c=A.useCallback(m=>t({type:"UPDATE_CURRENT_ANSWER",value:m}),[t]),T=A.useCallback(async m=>(await _(),t({type:"UPDATE_QUESTION_COORDINATES",value:m})),[t]),_=async()=>{let m=await l.getItem(`${e?.test?._id}-timers`)||{};e.test?.sections.forEach(k=>{k.questions?.forEach(R=>{m[R._id]&&!e.solutions[R._id]&&(e.solutions[R._id]={}),e.solutions[R._id]&&(e.solutions[R._id].timeTaken=m[R._id])})})},d=A.useCallback(m=>t({type:"UPDATE_USER_SETTINGS",value:m}),[t]),E=A.useCallback(m=>t({type:"UPDATE_TEST_SUBMITTING",value:m}),[t]);A.useEffect(()=>{e.isSolution||l.setItem(`${e.test?._id}-solutions`,e.solutions)},[e.solutions]);let i=A.useCallback(m=>t({type:"UPDATE_SOLUTIONS",value:m}),[t]),S=A.useCallback(async()=>{if(!await l.getItem(`${e.test?._id}-test-initiated`)&&e.test?.status==="Paused"){let k=await l.getItem(`${e?.test?._id}-timers`)||{},R={};e.test?.sections?.forEach((p,g)=>{p.questions?.forEach((I,v)=>{I._id===e.test?.lastVisitedQuestionId&&T({currentSectionIndex:g,currentQuestionIndex:v}),I.questionResponse&&(R[I._id]=JSON.stringify(I.questionResponse.timeTaken||0))})}),l.setItem(`${e?.test?._id}-timers`,{...k,...R})}e?.isSolution||l.setItem(`${e.test?._id}-test-initiated`,"true")},[]);A.useEffect(()=>{S()},[]);let a=async()=>{await l.removeItem(`${e.test?._id}-currentQuestionIndex`),await l.removeItem(`${e.test?._id}-currentSectionIndex`),await l.removeItem(`${e.test?._id}-solutions`),await l.removeItem(`${e.test?._id}-test-initiated`),await l.removeItem(`${e?.test?._id}-timers`)},f=A.useCallback(async(m=!1,k=!1)=>{E(!0);let R=await l.getItem(`${e.test?._id}-solutions`)||{},p=await l.getItem(`${e?.test?._id}-timers`)||{},g=[];e.test?.sections.forEach(v=>{v.questions.forEach(N=>{let P={questionId:N._id};R[N._id]&&(P.markedSolution=R[N._id].markedSolution||[],P.timeTaken=parseInt(p[N._id]||0),P.markedForReview=R[N._id].markedForReview||!1,g.push(P))})});let I={submittedBy:k?"autoSubmit":"user",questionResponses:g,testMappingId:e.test?.testMappingId,type:m?"Pause":"Submit",testId:e.test?._id};return m&&(I.lastVisitedQuestionId=u?._id),e.test?.timerLevel==="TEST"&&e.test.type==="TEST"&&m&&p[e?.test?._id]&&(I.timeTaken={[e.test?._id]:p[e?.test?._id]}),g.length||delete I.questionResponses,await a(),E(!1),o({payload:I,pause:m,autoSubmit:k}),I},[u]);return A.useMemo(()=>({...e,currentSection:s,currentQuestion:u,handleSubmitTest:f,handleUpdateTestDetails:r,handleUpdateQuestionCoordinates:T,handleUpdateSolutions:i,handleUpdateCurrentAnswer:c,handleUpdateUserSettings:d,handleResetLocal:a}),[e,s,u,f,r,T,i,c,d,a])},D=ee;import ne,{useCallback as C}from"react";var se=()=>{let{currentQuestion:n,currentQuestionAnswer:e,test:t,solutions:o,isSolution:s,handleUpdateCurrentAnswer:u,handleUpdateSolutions:r}=D(),c=ne.useMemo(()=>t?.type==="QUIZ"&&!!o[n?._id]?.markedSolution?.length,[t,o,n]),T=C(()=>{u({...e,markedSolution:[],isSaved:!1}),r({...o,[n?._id]:{...e,markedSolution:[]}})},[e,n,o,u,r]),_=C(i=>{if(!(s||c))if(e?.markedSolution?.includes(i)){let S=e.markedSolution.filter(a=>a!==i);return S?.length===0?T():u({...e,markedSolution:S,isSaved:!1})}else{if(n?.type==="SINGLE")return u({...e,markedSolution:[i],isSaved:!1});{let S=e?.markedSolution?.length?e?.markedSolution:[];return u({...e,markedSolution:[...S,i],isSaved:!1})}}},[s,c,n,e,u,T]),d=C(i=>{s||c||(u({...e,markedSolution:i?[i]:[],isSaved:!1}),i||T())},[s,c,u,e,T]),E=C(()=>{u({...e,markedForReview:!e?.markedForReview}),r({...o,[n._id]:{...o[n._id],markedForReview:!e?.markedForReview}})},[u,r,e,o,n]);return{isQuizAnswer:c,handleClearResponse:T,handleSelectOption:_,handleIntegerInputChange:d,handleMarkForReview:E}},L=se;import{useEffect as ie,useMemo as G,useState as oe}from"react";import W from"react";var re=({includeAllSections:n}={})=>{let{currentQuestionIndex:e,solutions:t,currentSectionIndex:o,test:s,isSolution:u}=D(),[r,c]=W.useState({MARKED_FOR_REVIEW:{count:0},ATTEMPTED:{count:0},ATTEMPTED_AND_MARKED_FOR_REVIEW:{count:0},NOT_ATTEMPTED:{count:0},NOT_VISITED:{count:0},ACITVE_QUESTION:{count:0}}),T=()=>{let i={...r};Object.values(i).forEach(S=>S.count=0),n?s?.sections?.forEach((S,a)=>{S?.questions?.forEach((f,U)=>{let m=u||s.type==="QUIZ"?E(U,a):_(U,a);i[m].count+=1})}):s?.sections[o]?.questions.forEach((S,a)=>{let f=u||s.type==="QUIZ"?E(a,o):_(a,o);i[f].count+=1}),c(i)};W.useEffect(()=>{T()},[e,t,o]);let _=(i,S)=>{let a=s?.sections[S]?.questions[i],f;return t[a?._id]&&t[a?._id].markedSolution?.length&&t[a?._id].markedForReview?f="ATTEMPTED_AND_MARKED_FOR_REVIEW":t[a?._id]&&t[a?._id].markedForReview?f="MARKED_FOR_REVIEW":t[a?._id]&&t[a?._id].markedSolution?.length?f="ATTEMPTED":t[a?._id]?f="NOT_ATTEMPTED":f="NOT_VISITED",f};function d(i,S){let a=i.slice().sort(),f=S.slice().sort();if(a.length!==f.length)return!1;for(let U=0;U<a.length;U++)if(a[U]!==f[U])return!1;return!0}let E=(i,S)=>{let a=s?.sections[S]?.questions[i],f;return t[a?._id]&&t[a?._id].markedSolution?.length?d(t[a?._id].markedSolution,a.solution)?f="ATTEMPTED":f="NOT_ATTEMPTED":f="NOT_VISITED",f};return{getQuestionStatus:_,questionStatusMap:r,getAnsweredQuestionStatus:E,areArraysEqual:d}},Q=re;var ue=()=>{let{handleUpdateQuestionCoordinates:n,currentQuestionIndex:e,currentSectionIndex:t,currentSection:o,currentQuestionAnswer:s,handleUpdateSolutions:u,solutions:r,currentQuestion:c,handleUpdateCurrentAnswer:T,test:_,userSettings:d}=D(),{getAnsweredQuestionStatus:E}=Q(),[i,S]=oe([]);ie(()=>{if(d?.selectedFilter){let p=o?.questions?.map((g,I)=>{if(d?.selectedFilter===E(I,t))return I})?.filter(g=>g!==void 0);S(p),p?.length&&n({currentSectionIndex:t,currentQuestionIndex:p[0]||0})}else S([])},[d?.selectedFilter,o]);let a=()=>{s?.isSaved||(delete s?.isSaved,u({...r,[c?._id]:{...s}}))},f=()=>{if(d?.selectedFilter){let I=i?.findIndex(v=>v===e);I>=0&&i[I+1]>=0&&n({currentSectionIndex:t,currentQuestionIndex:i[I+1]});return}let p=o?.questions[e+1]?t:_?.sections[t+1]?t+1:t,g=o?.questions[e+1]?e+1:0;n({currentSectionIndex:p,currentQuestionIndex:g})},U=()=>{if(d?.selectedFilter){let I=i?.findIndex(v=>v===e);I>=0&&i[I-1]>=0&&n({currentSectionIndex:t,currentQuestionIndex:i[I-1]});return}let p=o?.questions[e-1]?t:_?.sections[t-1]?t-1:t,g=o?.questions[e-1]?e-1:_.sections[p]?.questions?.length-1;n({currentSectionIndex:p,currentQuestionIndex:g})},m=G(()=>{if(d?.selectedFilter){let p=i?.findIndex(g=>g===e);return!i[p+1]}return!_?.sections[t+1]&&!o?.questions[e+1]},[t,e,i,d?.selectedFilter]),k=G(()=>d?.selectedFilter?i?.findIndex(g=>g===e)<=0:t===0&&e===0,[t,e,i,d?.selectedFilter]);return{handleNext:f,handlePrevious:U,handleSaveAnswer:a,handleMarkForReview:()=>{T({...s,markedForReview:!s?.markedForReview}),u({...r,[c._id]:{...r[c._id],markedForReview:!s?.markedForReview}})},isLastQuestion:m,isFirstQuestion:k}},ae=ue;import $ from"react";var B={1:{label:"A"},2:{label:"B"},3:{label:"C"},4:{label:"D"}},ce=()=>{let{currentQuestionIndex:n,test:e,currentSection:t,currentSectionIndex:o,currentQuestion:s}=D(),{getAnsweredQuestionStatus:u}=Q(),r=$.useMemo(()=>u(n,o)==="ATTEMPTED"?"correct":u(n,o)==="NOT_ATTEMPTED"?"incorrect":"skipped",[n,o]),c=$.useMemo(()=>{switch(r){case"correct":return e?.marksLevel==="TEST"?"+"+e.positiveMarks:"+"+t?.positiveMarks;case"incorrect":return e?.marksLevel==="TEST"?e.isNegativeMarkingEnabled?"-"+e.negativeMarks:0:t?.isNegativeMarkingEnabled?"-"+t?.negativeMarks:0;case"skipped":return 0}},[r,o,n]);return{correctAnswer:$.useMemo(()=>{if(!s)return"";if(s.type==="INTEGER")return s.solution[0];if(s.type==="SINGLE"){let _=s.options.findIndex(d=>d._id===s.solution[0]);return B[_+1]?.label||""}return s.type==="MULTIPLE"?s.solution.map(d=>{let E=s.options.findIndex(i=>i._id===d);return B[E+1]?.label||""}).join(", "):""},[s]),currentAnswerMarks:c,currentQuestionStatus:r}},le=ce;import M from"react";var de=()=>{let{test:n,handleSubmitTest:e}=D(),t=M.useRef(null),[o,s]=M.useState(n?.timeTaken?.[n?._id]??n?.duration??0),u=M.useCallback(async c=>{t.current&&clearTimeout(t.current);let T=await l.getItem(`${n?._id}-timers`);if(c<=0){e(!1,!0);return}T[n._id]=c+"",l.setItem(`${n?._id}-timers`,T),s(c),t.current=setTimeout(()=>{u(c-1)},1e3)},[n,e]),r=M.useCallback(async()=>{if(!n?._id)return;let c=await l.getItem(`${n._id}-timers`);c||(await l.setItem(`${n._id}-timers`,{}),c={});let T=parseInt(c?.[n._id]||n?.timeTaken?.[n._id]||n?.duration||0);u(T)},[n,u]);return M.useEffect(()=>(r(),()=>{t.current&&clearTimeout(t.current)}),[r,n?._id]),{timer:o}},Te=de;import h from"react";var me=n=>{let e=n==="app"?950:1e3,{currentQuestion:t,solutions:o,test:s}=D(),{isQuizAnswer:u}=L(),r=h.useRef(null),[c,T]=h.useState(0),_=async E=>{if(!t)return;let i=await l.getItem(`${s?._id}-timers`);if((o[t?._id]?.markedSolution||[])?.length===0)i[t?._id]=E+"",l.setItem(`${s?._id}-timers`,i),T(E);else{clearTimeout(r.current);return}r.current=setTimeout(()=>{_(E+1)},e)},d=async()=>{r.current&&(clearTimeout(r.current),r.current=null);let E=await l.getItem(`${s?._id}-timers`);E||(await l.setItem(`${s?._id}-timers`,{}),E={});let i=parseInt(E?.[t?._id]||s?.timeTaken?.[t?._id]||0);T(i),_(i)};return h.useEffect(()=>(t?._id&&d(),()=>{r.current&&(clearTimeout(r.current),r.current=null)}),[t]),h.useEffect(()=>{r.current===null&&setTimeout(()=>{r.current===null&&d()},e)},[o]),h.useEffect(()=>{u&&(clearTimeout(r.current),r.current=null)},[u]),{questionStopWatch:c}},Se=me;export{w as AttemptStatus,H as TestEngineProvider,Se as useQuestionStopWatch,D as useTestEngine,L as useTestEngineBody,ae as useTestEngineFooter,Q as useTestQuestionStatus,le as useTestSolutionBody,Te as useTestTimer};
1
+ var Z=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});import ne,{useMemo as q}from"react";import{create as J}from"zustand";import{persist as X,createJSONStorage as ee}from"zustand/middleware";var $=()=>typeof globalThis>"u"||!globalThis.localStorage?null:{setItem:(t,e)=>{globalThis.localStorage.setItem(t,e)},getItem:t=>globalThis.localStorage.getItem(t)??null,removeItem:t=>{globalThis.localStorage.removeItem(t)}},Y=()=>{try{let{createMMKV:t}=Z("react-native-mmkv"),e=t();return{setItem:(r,s)=>{e.set(r,s)},getItem:r=>e.getString(r)??null,removeItem:r=>{e.delete(r)}}}catch{return null}},N={},j=()=>({setItem:(t,e)=>{N[t]=e},getItem:t=>N[t]??null,removeItem:t=>{delete N[t]}}),Q=$()||Y()||j();import te from"react";var P={test:void 0,solutions:{},currentQuestionIndex:0,currentSectionIndex:0,currentQuestionAnswer:{},userSettings:{},isSolution:!1,submitting:!1,timer:{},isHydrated:!1},y=te.createContext([P,()=>{}]);y.displayName="TestEngineContext";var o=J()(X(t=>({...P,setQuestionCoordinates:(e,r)=>t(s=>{let n=s.test?.sections[e]?.questions[r]?._id,c=null;return s.isSolution||(s.solutions[n]?c={...s.solutions,[n]:{...s.solutions[n],timeTaken:s.timer[n]||0}}:c={...s.solutions,[n]:{}}),{currentSectionIndex:e,currentQuestionIndex:r,currentQuestionAnswer:c?.[n]||{},...c&&{solutions:c}}}),setTest:(e,r)=>t(()=>{if(!r)return{test:e};let s={},u={},i=0,n=0;e?.sections?.forEach((E,p)=>{E?.questions?.forEach((T,R)=>{T?.questionResponse&&(s={...s,[T?._id]:{markedSolution:T?.questionResponse?.markedSolution||[],markedForReview:T?.questionResponse?.markedForReview||!1,timeTaken:T?.questionResponse?.timeTaken||0,isSaved:!0}},u={...u,[T?._id]:T?.questionResponse?.timeTaken||0}),e?.status==="Paused"&&T._id===e?.lastVisitedQuestionId&&(i=p,n=R)})}),u[e?._id]=e?.timeTaken&&+e?.timeTaken[e?._id]||+e?.duration||0;let c=e?.sections[i]?.questions[n]?._id,m=s[c]||{};return{test:e,solutions:s,timer:u,currentSectionIndex:i,currentQuestionIndex:n,currentQuestionAnswer:m}}),setSolution:(e,r)=>t(s=>({solutions:{...s.solutions,[e]:{...s.solutions[e],...r}},currentQuestionAnswer:{...s.solutions[e],...r}})),incrementTimer:e=>t(r=>({timer:{...r.timer,[e]:(r.timer[e]||0)+1}})),decrementTimer:e=>t(r=>({timer:{...r.timer,[e]:(r.timer[e]||0)-1}})),setCurrentAnswer:e=>t({currentQuestionAnswer:e}),setUserSettings:e=>t({userSettings:e}),setTestSubmitting:e=>t({submitting:e}),reset:()=>t(P),setIsHydrated:e=>t({isHydrated:e})}),{name:"test-engine-v2-store",storage:ee(()=>Q)}));var re=()=>{let t=ne.useContext(y);if(t===void 0)throw new Error("useTestEngineV2 must be use within TestEngineProvider");let[e,r]=t;if(!e.test)throw new Error("Please provide test data to useTestEngineV2");let s=o(S=>S.test),u=o(S=>S.setTestSubmitting),i=o(S=>S.solutions),n=o(S=>S.currentQuestionIndex),c=o(S=>S.currentSectionIndex),m=q(()=>s?.sections[c],[s,c]),E=q(()=>m?.questions[n],[m,n]),p=o(S=>S.reset),T=o(S=>S.timer);return{handleSubmitTest:(S=!1,I=!1)=>{u(!0);let A=[];s?.sections?.forEach(f=>{f?.questions?.forEach(d=>{i[d._id]&&A.push({questionId:d._id,markedSolution:i[d._id]?.isSaved?i[d._id]?.markedSolution:[],timeTaken:T[d._id]||i[d._id]?.timeTaken||0,markedForReview:i[d._id]?.markedForReview||!1})})});let k={submittedBy:I?"autoSubmit":"user",questionResponses:A,testMappingId:s?.testMappingId,type:S?"Pause":"Submit",testId:s?._id,...S?{lastVisitedQuestionId:E?._id}:{},...s?.type==="TEST"&&S&&T[s?._id]?{timeTaken:{[s?._id]:T[s?._id]}}:{}};return A.length||delete k.questionResponses,u(!1),r({payload:k,pause:S,autoSubmit:I}),k},currentSection:m,currentQuestion:E,...o.getState(),...e}},D=re;import{useEffect as L,useRef as se}from"react";var oe=()=>{let{isSolution:t,handleSubmitTest:e}=D(),r=o(m=>m.test),s=o(m=>m.timer),u=o(m=>m.decrementTimer),i=o(m=>m.isHydrated),n=se(null),c=()=>{r&&i&&u(r?._id),n.current=setTimeout(()=>{c()},1e3)};return L(()=>{if(r&&s[r?._id]<=0){clearTimeout(n.current),e(!1,!0);return}},[s,r]),L(()=>{if(!t)return c(),()=>{n.current&&clearTimeout(n.current)}},[r,i]),{timer:s[r._id]||0}},ie=oe;import O,{useCallback as V}from"react";var C=(n=>(n.ATTEMPTED="ATTEMPTED",n.NOT_ATTEMPTED="NOT_ATTEMPTED",n.NOT_VISITED="NOT_VISITED",n.MARKED_FOR_REVIEW="MARKED_FOR_REVIEW",n.ATTEMPTED_AND_MARKED_FOR_REVIEW="ATTEMPTED_AND_MARKED_FOR_REVIEW",n.ACITVE_QUESTION="ACITVE_QUESTION",n))(C||{});var K={1:{label:"A"},2:{label:"B"},3:{label:"C"},4:{label:"D"}},ae=({includeAllSections:t}={})=>{let e=o(f=>f.test),r=o(f=>f.solutions),s=o(f=>f.isSolution),u=o(f=>f.currentSectionIndex),{currentQuestion:i,currentSection:n}=D(),c=o(f=>f.currentQuestionIndex),[m,E]=O.useState({MARKED_FOR_REVIEW:{count:0},ATTEMPTED:{count:0},ATTEMPTED_AND_MARKED_FOR_REVIEW:{count:0},NOT_ATTEMPTED:{count:0},NOT_VISITED:{count:0},ACITVE_QUESTION:{count:0}}),p=V((f,d)=>{let a=e?.sections[d]?.questions[f],g=r[a?._id];return g?g?.markedSolution&&g?.markedSolution?.length>0&&g?.markedForReview?"ATTEMPTED_AND_MARKED_FOR_REVIEW":g?.markedSolution&&g?.markedSolution?.length>0?"ATTEMPTED":g?.markedForReview?"MARKED_FOR_REVIEW":"NOT_ATTEMPTED":"NOT_VISITED"},[r,e]),T=V((f,d)=>{let a=e?.sections[d]?.questions[f],g=r[a?._id];return g?.markedSolution?.length?S(g.markedSolution,a.solution)?"ATTEMPTED":"NOT_ATTEMPTED":"NOT_VISITED"},[r,e]),R=V(()=>{let f={...m};Object.values(f).forEach(d=>d.count=0),t?e?.sections?.forEach((d,a)=>{d?.questions?.forEach((g,M)=>{let w=s||e.type==="QUIZ"?T(M,a):p(M,a);f[w].count+=1})}):e?.sections[u]?.questions.forEach((d,a)=>{let g=s||e.type==="QUIZ"?T(a,u):p(a,u);f[g].count+=1}),E(f)},[T,p,t,s,e,u,r]);O.useEffect(()=>{R()},[c,r,u]);function S(f,d){let a=f.slice().sort(),g=d.slice().sort();if(a.length!==g.length)return!1;for(let M=0;M<a.length;M++)if(a[M]!==g[M])return!1;return!0}let I=O.useMemo(()=>T(c,u)==="ATTEMPTED"?"correct":T(c,u)==="NOT_ATTEMPTED"?"incorrect":"skipped",[c,u,T]),A=O.useMemo(()=>{switch(I){case"correct":return e?.marksLevel==="TEST"?"+"+e.positiveMarks:"+"+n?.positiveMarks;case"incorrect":return e?.marksLevel==="TEST"?e.isNegativeMarkingEnabled?"-"+e.negativeMarks:0:n?.isNegativeMarkingEnabled?"-"+n?.negativeMarks:0;case"skipped":return 0}},[I]),k=O.useMemo(()=>{if(!i)return"";if(i.type==="INTEGER")return i.solution[0];if(i.type==="SINGLE"){let f=i.options.findIndex(d=>d._id===i.solution[0]);return K[f+1]?.label||""}return i.type==="MULTIPLE"?i.solution.map(d=>{let a=i.options.findIndex(g=>g._id===d);return K[a+1]?.label||""}).join(", "):""},[i]);return{getQuestionStatus:p,questionStatusMap:m,getAnsweredQuestionStatus:T,areArraysEqual:S,currentQuestionStatus:I,currentAnswerMarks:A,correctAnswer:k}},U=ae;import{useEffect as ce,useRef as de}from"react";var le=()=>{let{currentQuestion:t,isSolution:e}=D(),r=o(m=>m.timer),s=o(m=>m.incrementTimer),u=o(m=>m.solutions),i=o(m=>m.isHydrated),n=de(null),c=()=>{t&&!u[t?._id]?.markedSolution?.length&&i&&s(t?._id),n.current=setTimeout(()=>{c()},1e3)};return ce(()=>{if(!e)return c(),()=>{n.current&&clearTimeout(n.current)}},[t,u,i]),{timer:r[t._id]||0}},me=le;import Te,{useCallback as h,useEffect as Se,useMemo as W,useState as fe}from"react";var ge=()=>{let t=o(l=>l.test),e=o(l=>l.solutions),{currentQuestion:r,currentSection:s,currentQuestionAnswer:u}=D(),i=o(l=>l.currentQuestionIndex),n=o(l=>l.currentSectionIndex),c=o(l=>l.userSettings),m=o(l=>l.isSolution),E=o(l=>l.setQuestionCoordinates),p=o(l=>l.setSolution),T=o(l=>l.setCurrentAnswer),{getAnsweredQuestionStatus:R}=U(),S=Te.useMemo(()=>t?.type==="QUIZ"&&!!e[r?._id]?.markedSolution?.length,[t,e,r]),I=h(()=>{T({...u,markedSolution:[],isSaved:!1}),p(r?._id,{...u,markedSolution:[]})},[u,r,p]),A=h(l=>{if(!(m||S))if(u?.markedSolution?.includes(l)){let _=u.markedSolution.filter(b=>b!==l);if(_?.length===0)return I();T({...u,markedSolution:_,isSaved:!1});return}else if(r?.type==="SINGLE"){T({...u,markedSolution:[l],isSaved:!1});return}else{let _=u?.markedSolution?.length?u?.markedSolution:[];T({...u,markedSolution:[..._,l],isSaved:!1});return}},[m,S,r,u,T,I]),k=h(l=>{m||S||(T({...u,markedSolution:l?[l]:[],isSaved:!1}),l||I())},[m,S,u,I]),f=h(()=>{T({...u,markedForReview:!u?.markedForReview}),p(r._id,{...e[r._id],markedForReview:!u?.markedForReview})},[p,u,e,r]),[d,a]=fe([]);Se(()=>{if(c?.selectedFilter){let l=s?.questions?.map((_,b)=>{if(c?.selectedFilter===R(b,n))return b})?.filter(_=>_!==void 0);a(l),l?.length&&E(n,l[0]||0)}else a([])},[c,s,R,E]);let g=h(()=>{u?.isSaved||p(r?._id,{...u,isSaved:!0})},[u,r,p]),M=h(()=>{if(c?.selectedFilter){let b=d?.findIndex(F=>F===i);b>=0&&d[b+1]>=0&&E(n,d[b+1]);return}let l=s?.questions[i+1]?n:t?.sections[n+1]?n+1:n,_=s?.questions[i+1]?i+1:0;E(l,_)},[c?.selectedFilter,d,i,n,s,t,E]),w=h(()=>{if(c?.selectedFilter){let b=d?.findIndex(F=>F===i);b>=0&&d[b-1]>=0&&E(n,d[b-1]);return}let l=s?.questions[i-1]?n:t?.sections[n-1]?n-1:n,_=s?.questions[i-1]?i-1:t.sections[l]?.questions?.length-1;E(l,_)},[c?.selectedFilter,d,i,n,s,t,E]),z=W(()=>{if(c?.selectedFilter){let l=d?.findIndex(_=>_===i);return!d[l+1]}return!t?.sections[n+1]&&!s?.questions[i+1]},[n,i,d,c?.selectedFilter,t,s]),B=W(()=>c?.selectedFilter?d?.findIndex(_=>_===i)<=0:n===0&&i===0,[n,i,d,c?.selectedFilter]);return{isQuizAnswer:S,handleClearResponse:I,handleSelectOption:A,handleIntegerInputChange:k,handleMarkForReview:f,handleNext:M,handlePrevious:w,handleSaveAnswer:g,isLastQuestion:z,isFirstQuestion:B}},Ee=ge;import{useEffect as pe,forwardRef as Ie,useImperativeHandle as _e}from"react";import G from"react";var be=Ie(({test:t,isSolution:e,submitTest:r,children:s},u)=>{let i=o(a=>a.setTest),n=o(a=>a.setIsHydrated),c=o(a=>a.isHydrated),m=o(a=>a.test),E=o(a=>a.solutions),p=o(a=>a.currentQuestionIndex),T=o(a=>a.currentSectionIndex),R=o(a=>a.currentQuestionAnswer),S=o(a=>a.userSettings),I=o(a=>a.submitting),A=o(a=>a.timer),k=o(a=>a.reset),f=G.useMemo(()=>({test:m,solutions:E,currentQuestionIndex:p,currentSectionIndex:T,userSettings:S,isSolution:e||!1,submitting:I,timer:A,isHydrated:c,currentQuestionAnswer:R}),[m,E,p,T,S,e,I,A,c,R]),d=()=>{console.log("[RESET]: Called"),k(),Q.removeItem(`${t?._id}-test-initiated`),Q.removeItem(`test-engine-v2-store-${t?._id}`),Q.removeItem("test-engine-v2-store")};return _e(u,()=>({reset:d})),pe(()=>{(async()=>{if(!(c&&t?._id===m?._id))try{Q.getItem(`${t?._id}-test-initiated`)?i(t,!1):(i(t,!0),e||Q.setItem(`${t?._id}-test-initiated`,"true")),o.persist.setOptions({name:`test-engine-v2-store-${t?._id}`}),await o.persist.rehydrate(),Q.removeItem("test-engine-v2-store"),n(!0)}catch(g){console.error("Error initializing test engine store:",g),n(!0)}})()},[t?._id,c,i,n]),!c||!m?null:G.createElement(y.Provider,{value:[f,r]},s)}),Re=be;export{C as AttemptStatus,Re as TestEngineProvider,me as useQuestionTimer,U as useQuestions,Ee as useTestActions,D as useTestEngine,ie as useTestTimer};
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "testforce-engine",
3
- "version": "0.0.3-alpha",
3
+ "version": "1.0.0-beta-1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
9
9
  "build": "tsup",
10
+ "build:watch": "tsup --watch",
10
11
  "prepare": "npm run build"
11
12
  },
12
13
  "keywords": [],
@@ -17,13 +18,15 @@
17
18
  },
18
19
  "devDependencies": {
19
20
  "@types/react": "18.3.1",
21
+ "react-native-mmkv": "^4.1.1",
20
22
  "tsup": "^8.3.6",
21
- "typescript": "^5.7.3"
23
+ "typescript": "^5.7.3",
24
+ "zustand": "^5.0.10"
22
25
  },
23
26
  "peerDependencies": {
24
- "react": ">=18",
25
- "react-dom": ">=18",
26
- "react-native": ">=0.76",
27
- "react-native-mmkv": ">=3.2"
27
+ "react": "18.3.1",
28
+ "react-native": "0.76.9",
29
+ "react-native-mmkv": ">=4",
30
+ "zustand": ">=5"
28
31
  }
29
32
  }