l-min-components 1.7.1405 → 1.7.1407

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "l-min-components",
3
- "version": "1.7.1405",
3
+ "version": "1.7.1407",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/assets",
@@ -1,78 +1,51 @@
1
- import React, { useState } from "react";
2
- import Truncate from "react-truncate";
1
+ import React, { useState, useRef, useEffect } from "react";
3
2
  import styled from "styled-components";
4
3
 
5
4
  const InlineClampedText = ({ text }) => {
6
5
  const [isExpanded, setIsExpanded] = useState(false);
7
- const [truncated, setTruncated] = useState(false);
6
+ const [isClamped, setIsClamped] = useState(false);
7
+ const textRef = useRef(null);
8
+
9
+ useEffect(() => {
10
+ const el = textRef.current;
11
+ if (el) {
12
+ // Check if the text is clamped by comparing scrollHeight and offsetHeight
13
+ setIsClamped(el.scrollHeight > el.offsetHeight);
14
+ }
15
+ }, [text]);
8
16
 
9
17
  return (
10
18
  <Container>
11
- {!isExpanded ? (
12
- <Truncate
13
- lines={2}
14
- ellipsis={
15
- truncated ? (
16
- <>
17
- ...{" "}
18
- <span
19
- onClick={() => setIsExpanded(true)}
20
- style={{
21
- cursor: "pointer",
22
- color: "#00C2C2",
23
- fontSize: "14px",
24
- }}
25
- >
26
- See more
27
- </span>
28
- </>
29
- ) : (
30
- ""
31
- )
32
- }
33
- onTruncate={(trunc) => setTruncated(trunc)}
34
- >
35
- <span
36
- style={{
37
- color: "#4A4D4D",
38
- fontSize: "14px",
39
- }}
40
- >
41
- {text}
42
- </span>
43
- </Truncate>
44
- ) : (
45
- <>
46
- <span
47
- style={{
48
- color: "#4A4D4D",
49
- fontSize: "14px",
50
- }}
51
- >
52
- {text}
53
- </span>{" "}
54
- {truncated && (
55
- <span
56
- onClick={() => setIsExpanded(false)}
57
- style={{
58
- cursor: "pointer",
59
- color: "#00C2C2",
60
- fontSize: "14px",
61
- }}
62
- >
63
- Show less
64
- </span>
65
- )}
66
- </>
19
+ <TextWrapper isExpanded={isExpanded} ref={textRef}>
20
+ {text}
21
+ </TextWrapper>
22
+ {isClamped && (
23
+ <Toggle onClick={() => setIsExpanded(!isExpanded)}>
24
+ {isExpanded ? "Show less" : "See more"}
25
+ </Toggle>
67
26
  )}
68
27
  </Container>
69
28
  );
70
29
  };
71
30
 
72
31
  const Container = styled.div`
73
- span {
74
- font-size: 14px !important;
75
- }
32
+ font-size: 14px;
33
+ color: #4a4d4d;
34
+ `;
35
+
36
+ const TextWrapper = styled.div`
37
+ overflow: hidden;
38
+ display: -webkit-box;
39
+ -webkit-line-clamp: ${(props) => (props.isExpanded ? "unset" : 2)};
40
+ -webkit-box-orient: vertical;
41
+ white-space: normal;
42
+ `;
43
+
44
+ const Toggle = styled.span`
45
+ color: #00c2c2;
46
+ font-size: 14px;
47
+ cursor: pointer;
48
+ margin-left: 5px;
76
49
  `;
77
50
 
78
51
  export default InlineClampedText;
@@ -17,7 +17,7 @@ import PenIcon from "../icons/pen";
17
17
  import Mircophone from "../icons/mircophone";
18
18
  import { Se, Tr } from "react-flags-select";
19
19
  import Table from "./table";
20
- import TranslateDropdown from "./translateDropdown";
20
+ // import TranslateDropdown from "./translateDropdown";
21
21
  import { Progress } from "rsuite";
22
22
  import ClarityItem from "./ClarityItem";
23
23
  import InlineClampedText from "./InlineClampedText";
@@ -119,7 +119,7 @@ const SpeechAnalysis = ({ Aidata }) => {
119
119
  <span>Grade</span>
120
120
  <div className="space-between">
121
121
  <span>Feedback</span>
122
- <TranslateDropdown />
122
+ {/* <TranslateDropdown /> */}
123
123
  </div>
124
124
  </div>
125
125
  <div className="table_row">
@@ -157,6 +157,7 @@ const SpeechAnalysis = ({ Aidata }) => {
157
157
  </div>
158
158
  </div>
159
159
  <InlineClampedText
160
+ key={item?.id}
160
161
  text={item?.["Phoneme Feedback"] || ""}
161
162
  />
162
163
  </div>
@@ -289,7 +290,7 @@ const SpeechAnalysis = ({ Aidata }) => {
289
290
 
290
291
  <div className="space-between">
291
292
  <span>Feedback</span>
292
- <TranslateDropdown />
293
+ {/* <TranslateDropdown /> */}
293
294
  </div>
294
295
  </div>
295
296
  <div className="table_row">
@@ -305,7 +306,10 @@ const SpeechAnalysis = ({ Aidata }) => {
305
306
  {item?.score} {item?.total ? `of ${item?.total}` : ""}
306
307
  </p>
307
308
  <p>
308
- <InlineClampedText text={item?.feedback || ""} />
309
+ <InlineClampedText
310
+ key={item?.title}
311
+ text={item?.feedback || ""}
312
+ />
309
313
  </p>
310
314
  </div>
311
315
  ))}
@@ -20,7 +20,6 @@ import Grammar from "./components/Grammar";
20
20
 
21
21
  const FullAnalysis = ({ data, onClose }) => {
22
22
  const { setRightLayout, setCenterLayoutStyle } = useContext(OutletContext);
23
- const [selected, setSelected] = useState(null);
24
23
 
25
24
  // const colors = [
26
25
  // { main: "#009999", sub: "#E6F9F9" },
@@ -32,10 +31,11 @@ const FullAnalysis = ({ data, onClose }) => {
32
31
  label: item?.label,
33
32
  value: item?.id,
34
33
  }));
34
+ const [selected, setSelected] = useState(tabs?.[0]?.value || "");
35
35
 
36
36
  useEffect(() => {
37
37
  if (tabs?.length) {
38
- setSelected(tabs?.[0]?.value);
38
+ setSelected(tabs[0].value);
39
39
  }
40
40
  }, [tabs?.length]);
41
41
 
@@ -127,25 +127,28 @@ const FullAnalysis = ({ data, onClose }) => {
127
127
  </p>
128
128
  </ProgressCircleSection>
129
129
  <ul>
130
- {data?.models?.map((model) => (
131
- <li key={model?.id}>
132
- <p>{`${model?.label} point`}</p>
133
- <div style={{ backgroundColor: model?.bgColor }}>
134
- <span style={{ color: model?.primaryColor }}>
135
- {model?.score || 0}%
136
- </span>
137
- <Progress.Line
138
- percent={model?.score || 0}
139
- strokeWidth={4}
140
- trailWidth={4}
141
- strokeColor={model?.primaryColor}
142
- trailColor={"#fff"}
143
- showInfo={false}
144
- style={{ width: "100%" }}
145
- />
146
- </div>
147
- </li>
148
- ))}
130
+ {data?.models?.map((model) => {
131
+ if (model?.id === "logic_evaluation") return null;
132
+ return (
133
+ <li key={model?.id}>
134
+ <p>{`${model?.label} point`}</p>
135
+ <div style={{ backgroundColor: model?.bgColor }}>
136
+ <span style={{ color: model?.primaryColor }}>
137
+ {model?.score || 0}%
138
+ </span>
139
+ <Progress.Line
140
+ percent={model?.score || 0}
141
+ strokeWidth={4}
142
+ trailWidth={4}
143
+ strokeColor={model?.primaryColor}
144
+ trailColor={"#fff"}
145
+ showInfo={false}
146
+ style={{ width: "100%" }}
147
+ />
148
+ </div>
149
+ </li>
150
+ );
151
+ })}
149
152
  </ul>
150
153
  </ProgressSidebar>
151
154
  {selectedModel?.id === "speech_analysis" && (
@@ -159,7 +162,9 @@ const FullAnalysis = ({ data, onClose }) => {
159
162
  )}
160
163
  </Sidebar>
161
164
  <MainSection>
162
- <Tabs options={tabs} selected={selected} onChange={setSelected} />
165
+ {tabs?.length > 0 && (
166
+ <Tabs options={tabs} selected={selected} onChange={setSelected} />
167
+ )}
163
168
  {selectedModel?.id === "logic_evaluation" && (
164
169
  <Evaluation Aidata={selectedModel} />
165
170
  )}
@@ -0,0 +1,114 @@
1
+ import useAxios from "axios-hooks";
2
+
3
+ const useApi = () => {
4
+ const [{ ...addCommentData }, addComment] = useAxios(
5
+ {
6
+ method: "POST",
7
+ },
8
+ {
9
+ manual: true,
10
+ }
11
+ );
12
+
13
+ const handleAddComment = async (
14
+ question_activity_id,
15
+ test_id,
16
+ data,
17
+ enterprise_id
18
+ ) => {
19
+ try {
20
+ const url = enterprise_id
21
+ ? `/learn/v1/instructor/${enterprise_id}/tests/${test_id}/add_comment/${question_activity_id}/`
22
+ : `/learn/v1/instructor/tests/${test_id}/add_comment/${question_activity_id}/`;
23
+ return await addComment({
24
+ url,
25
+ data,
26
+ });
27
+ } catch (err) {
28
+ console.log(err);
29
+ }
30
+ };
31
+
32
+ const [{ ...gradeQuestionData }, gradeQuestion] = useAxios(
33
+ {
34
+ method: "POST",
35
+ },
36
+ {
37
+ manual: true,
38
+ }
39
+ );
40
+
41
+ const handleGradeQuestion = async (
42
+ question_activity_id,
43
+ session_id,
44
+ data,
45
+ enterprise_id
46
+ ) => {
47
+ try {
48
+ const url = enterprise_id
49
+ ? `/learn/v1/instructor/${enterprise_id}/tests/${question_activity_id}/submit_score/${session_id}/`
50
+ : `/learn/v1/instructor/tests/${question_activity_id}/submit_score/${session_id}/`;
51
+ return await gradeQuestion({
52
+ url,
53
+ data: {
54
+ ...data,
55
+ },
56
+ });
57
+ } catch (err) {
58
+ console.log(err);
59
+ }
60
+ };
61
+
62
+ const [{ ...deleteCommentData }, deleteComment] = useAxios(
63
+ {
64
+ method: "POST",
65
+ },
66
+ {
67
+ manual: true,
68
+ }
69
+ );
70
+
71
+ const handleDeleteComment = async (
72
+ question_activity_id,
73
+ test_id,
74
+ index,
75
+ enterprise_id
76
+ ) => {
77
+ try {
78
+ const url = enterprise_id
79
+ ? `/learn/v1/instructor/${enterprise_id}/tests/${test_id}/delete_comment/${question_activity_id}/?index=${index}`
80
+ : `/learn/v1/instructor/tests/${test_id}/delete_comment/${question_activity_id}/?index=${index}`;
81
+ return await deleteComment({
82
+ url,
83
+ });
84
+ } catch (err) {
85
+ console.log(err);
86
+ }
87
+ };
88
+ const [{ ...uploadData }, upload] = useAxios(
89
+ {
90
+ method: "POST",
91
+ },
92
+ { manual: true }
93
+ );
94
+
95
+ const handleUpload = async (data) => {
96
+ return await upload({
97
+ url: "/media/v1/instructor/files/",
98
+ data,
99
+ });
100
+ };
101
+
102
+ return {
103
+ addCommentData,
104
+ handleAddComment,
105
+ handleGradeQuestion,
106
+ gradeQuestionData,
107
+ deleteCommentData,
108
+ handleDeleteComment,
109
+ handleUpload,
110
+ uploadData,
111
+ };
112
+ };
113
+
114
+ export default useApi;
@@ -16,22 +16,38 @@ import DeleteIcon from "../../../../assets/svg/delete-icon";
16
16
  import moment from "moment";
17
17
  import ResponseAudio from "./responseAudio";
18
18
  import DeleteModal from "./modals/deleteModal";
19
- import { AudioWaveComponent, OutletContext, useAudioPlayer } from "../../..";
19
+ import {
20
+ AudioWaveComponent,
21
+ FullPageLoader,
22
+ OutletContext,
23
+ useAudioPlayer,
24
+ } from "../../..";
20
25
  import { CloseIcon } from "../../../header/assets/svg/close";
21
26
  import classNames from "classnames";
22
27
  import { useRecorder } from "react-microphone-recorder";
23
28
  import PlayIcon from "../../../../assets/svg/playIcon";
24
29
  import styled from "styled-components";
25
30
  import { FaPause } from "react-icons/fa";
31
+ import useApi from "../api";
26
32
  /**
27
33
  * @param {Object} props
28
34
  * @param {boolean} props.editMode
29
35
  * @returns {React.ReactNode}
30
36
  */
31
- const Comment = ({ editMode = false, data, accountType }) => {
37
+ const Comment = ({ editMode = false, data, testId, questionData, setData }) => {
32
38
  const { affiliateAccount } = useContext(OutletContext);
33
39
  const [toggleDelete, setToggleDelete] = useState(false);
34
40
  const [showForm, setShowForm] = useState(null);
41
+ const [value, setValue] = useState("");
42
+ const {
43
+ handleAddComment,
44
+ addCommentData,
45
+ handleDeleteComment,
46
+ deleteCommentData,
47
+ handleUpload,
48
+ uploadData,
49
+ } = useApi();
50
+ const enterpriseId = affiliateAccount?.id;
35
51
 
36
52
  const {
37
53
  startRecording,
@@ -41,7 +57,6 @@ const Comment = ({ editMode = false, data, accountType }) => {
41
57
  resetRecording,
42
58
  recordingState,
43
59
  } = useRecorder();
44
- console.log(data);
45
60
 
46
61
  if (!editMode && !data) return;
47
62
 
@@ -50,10 +65,76 @@ const Comment = ({ editMode = false, data, accountType }) => {
50
65
  { text: "Audio", icon: AudioIcon },
51
66
  ];
52
67
 
68
+ const handleComment = async () => {
69
+ if (!enterpriseId || !testId || !questionData?.question_activity_id) return;
70
+
71
+ if (showForm === "Text") {
72
+ const data = { data: { data: { type: "text", text: value } } };
73
+ const res = await handleAddComment(
74
+ questionData?.question_activity_id,
75
+ testId,
76
+ data,
77
+ enterpriseId
78
+ );
79
+ if (res?.data) {
80
+ const comment = res?.data?.data?.answer?.comments?.[0];
81
+ setData(comment);
82
+ setShowForm(null);
83
+ setValue("");
84
+ }
85
+ } else {
86
+ const formData = new FormData();
87
+ formData.append("upload", audioFile);
88
+ const resMedia = await handleUpload(formData);
89
+ const media = resMedia?.data?.results?.[0];
90
+ if (media) {
91
+ const data = { data: { data: { type: "audio", audio: media } } };
92
+ const res = await handleAddComment(
93
+ questionData?.question_activity_id,
94
+ testId,
95
+ data,
96
+ enterpriseId
97
+ );
98
+ if (res?.data) {
99
+ const comment = res?.data?.data?.answer?.comments?.[0];
100
+ setData(comment);
101
+ setShowForm(null);
102
+ resetRecording();
103
+ }
104
+ }
105
+ }
106
+ };
107
+
108
+ const disabled = showForm === "Text" ? !value : !audioFile;
109
+
110
+ const handleDelete = async () => {
111
+ if (!enterpriseId || !testId || !questionData?.question_activity_id) return;
112
+
113
+ const res = await handleDeleteComment(
114
+ questionData?.question_activity_id,
115
+ testId,
116
+ 0,
117
+ enterpriseId
118
+ );
119
+
120
+ if (res?.data) {
121
+ setData(null);
122
+ setToggleDelete(false);
123
+ setValue("");
124
+ setShowForm(null);
125
+ }
126
+ };
127
+
128
+ console.log(data);
129
+
53
130
  return (
54
131
  <CommentContainer>
132
+ {(addCommentData?.loading ||
133
+ deleteCommentData?.loading ||
134
+ uploadData?.loading) && <FullPageLoader fixed hasBackground />}
55
135
  {toggleDelete && (
56
136
  <DeleteModal
137
+ onClick={handleDelete}
57
138
  close={() => {
58
139
  setToggleDelete(false);
59
140
  }}
@@ -126,7 +207,13 @@ const Comment = ({ editMode = false, data, accountType }) => {
126
207
  <>
127
208
  <CommentContentForm>
128
209
  {showForm === "Text" && (
129
- <textarea placeholder="Input comment here" />
210
+ <textarea
211
+ placeholder="Input comment here"
212
+ value={value}
213
+ onChange={(e) => {
214
+ setValue(e?.target?.value);
215
+ }}
216
+ />
130
217
  )}
131
218
  {showForm === "Audio" && (
132
219
  <AudioRecordPlayer
@@ -161,7 +248,13 @@ const Comment = ({ editMode = false, data, accountType }) => {
161
248
  </li>
162
249
  ))}
163
250
  </ul>
164
- <button className="sm-btn">Send</button>
251
+ <button
252
+ className="sm-btn"
253
+ disabled={disabled}
254
+ onClick={handleComment}
255
+ >
256
+ Send
257
+ </button>
165
258
  </CommentContentAction>
166
259
  </>
167
260
  )}
@@ -4,7 +4,7 @@ import styled from "styled-components";
4
4
  import Radio from "../radio";
5
5
  import ButtonComponent from "../../../../button";
6
6
 
7
- const GradingModal = ({ aiValue, onClose }) => {
7
+ const GradingModal = ({ aiValue, onClose, setScore }) => {
8
8
  const [selected, setSelected] = useState("manually");
9
9
  const [value, setValue] = useState("");
10
10
 
@@ -12,8 +12,18 @@ const GradingModal = ({ aiValue, onClose }) => {
12
12
  setValue("");
13
13
  }, [selected]);
14
14
 
15
+ const numberValue = Number(value || 0);
16
+ const disable = selected === "manually" && (numberValue > 100 || !value);
17
+
15
18
  const isNumbter = typeof aiValue === "number";
16
19
 
20
+ const handleSetValue = () => {
21
+ setScore?.({
22
+ score_method: selected === "manually" ? "MANUAL" : "AI",
23
+ score: selected === "manually" ? numberValue : aiValue,
24
+ });
25
+ };
26
+
17
27
  return (
18
28
  <Container>
19
29
  <Wrapper>
@@ -66,7 +76,11 @@ const GradingModal = ({ aiValue, onClose }) => {
66
76
  )}
67
77
  </div>
68
78
  </TopSection>
69
- <ButtonComponent text="Save score" />
79
+ <ButtonComponent
80
+ text="Save score"
81
+ disabled={disable}
82
+ onClick={handleSetValue}
83
+ />
70
84
  </Content>
71
85
  </Wrapper>
72
86
  </Container>
@@ -30,6 +30,10 @@ export const CommentContainer = styled.div`
30
30
  border: none;
31
31
  outline: none;
32
32
  cursor: pointer;
33
+ &:disabled {
34
+ background: #c6cccc;
35
+ box-shadow: none;
36
+ }
33
37
  }
34
38
  `;
35
39
 
@@ -248,8 +248,8 @@ const essayUnscripted = {
248
248
  };
249
249
 
250
250
  const soundPlay = {
251
- question_id: 3104,
252
- question_activity_id: 8398,
251
+ question_id: 3078,
252
+ question_activity_id: 8384,
253
253
  position_index: 0,
254
254
  title: "Say the sentence",
255
255
  type: "SOUND_PLAY",
@@ -265,36 +265,42 @@ const soundPlay = {
265
265
  instruction: "Say the sentence",
266
266
  },
267
267
  answer: {
268
- session_id: "e0b8fb0cc6a0413e8a48af124c402965",
268
+ session_id: "17c9403e6b2c4761a06bf1ac22fffaf2",
269
269
  attempt_index: 1,
270
270
  token_claimed: 0,
271
271
  score: null,
272
272
  marked: false,
273
273
  expire_at: null,
274
- created_at: "2025-07-12T11:31:29.582953Z",
274
+ created_at: "2025-07-09T11:28:33.281076Z",
275
275
  grading_date: null,
276
276
  data: {
277
277
  type: "SOUND_PLAY",
278
- session_id: "67de7580ce91451",
279
- submited_datetime: "2025-07-09T16:23:04.549143Z",
278
+ session_id: "b269deece28047f",
279
+ submited_datetime: "2025-07-09T09:57:10.44195Z",
280
280
  audio: {
281
- id: "c08f8475036344abbba8c0c6daa1f14f",
282
- url: "https://dev-117782726-api.learngual.com/media/v1/files/c08f8475036344abbba8c0c6daa1f14f/stream/",
281
+ id: "1c06b5d866054d9fba5d67d14eeff436",
282
+ url: "https://dev-117782726-api.learngual.com/media/v1/files/1c06b5d866054d9fba5d67d14eeff436/stream/",
283
283
  stream_url: null,
284
284
  mimetype: "audio/mpeg",
285
- size: 29795.0,
286
- created_at: "2025-07-12T11:31:27.031742Z",
287
- updated_at: "2025-07-13T17:15:13.37607Z",
285
+ size: 54500.0,
286
+ created_at: "2025-07-09T11:28:23.930419Z",
287
+ updated_at: "2025-07-14T06:00:38.441656Z",
288
288
  uploaded_media_url: null,
289
289
  convertion_status: "DONE",
290
290
  },
291
291
  },
292
- comments: null,
292
+ comments: [],
293
293
  },
294
- score: 0,
295
- ai_score: 10.0,
296
- grading_data: {},
297
- grade_method: "MANUAL",
294
+ score: 100.0,
295
+ ai_score: 100.0,
296
+ grading_data: {
297
+ base_url: "https://dev-117782726-api.learngual.com/",
298
+ grader_id: "e4b92c77e5",
299
+ session_id: "17c9403e6b2c4761a06bf1ac22fffaf2",
300
+ score: 100.0,
301
+ grade_method: "AI",
302
+ },
303
+ grade_method: "AI",
298
304
  suggested_score: null,
299
305
  };
300
306
 
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from "react";
1
+ import React, { useContext, useEffect, useState } from "react";
2
2
  import constants, {
3
3
  aiWordSample,
4
4
  sampleResponse,
@@ -37,6 +37,9 @@ import DialogueUnscripted from "./questions/dialogueUnscripted";
37
37
  import GradingModal from "./components/modals/gradingModal";
38
38
  import classNames from "classnames";
39
39
  import FullAnalysis from "../fullAnalysis";
40
+ import useApi from "./api";
41
+ import FullPageLoader from "../../fullPageLoader";
42
+ import { OutletContext } from "../..";
40
43
 
41
44
  /**
42
45
  * @param {Object} props
@@ -52,10 +55,15 @@ const ReportQuestions = ({
52
55
  data,
53
56
  AiData,
54
57
  onClose,
58
+ testId,
55
59
  }) => {
56
60
  const [comment, setComment] = useState(null);
61
+ const [intructorScore, setInstructorScore] = useState(0);
57
62
  const [toggleGrade, setToggleGrade] = useState(false);
58
63
  const [toggle, setToggle] = useState(null);
64
+ const { affiliateAccount } = useContext(OutletContext);
65
+ const enterpriseId = affiliateAccount?.id;
66
+ const { handleGradeQuestion, gradeQuestionData } = useApi();
59
67
  const question = constants.questions.find(
60
68
  (question) => question.value === questionType
61
69
  );
@@ -63,7 +71,32 @@ const ReportQuestions = ({
63
71
 
64
72
  useEffect(() => {
65
73
  if (commentData?.length) setComment(commentData?.[0]);
66
- }, [commentData]);
74
+ }, [commentData, data?.question_id]);
75
+
76
+ useEffect(() => {
77
+ if (data?.question_id) {
78
+ setInstructorScore(data?.score);
79
+ }
80
+ }, [data?.question_id]);
81
+
82
+ const handleScore = async (value) => {
83
+ if (
84
+ !data?.question_activity_id ||
85
+ !enterpriseId ||
86
+ !data?.answer?.session_id
87
+ )
88
+ return;
89
+ const res = await handleGradeQuestion(
90
+ data?.question_activity_id,
91
+ data?.answer?.session_id,
92
+ value,
93
+ enterpriseId
94
+ );
95
+ if (res?.data) {
96
+ setInstructorScore(value?.score);
97
+ setToggleGrade(false);
98
+ }
99
+ };
67
100
 
68
101
  if (toggle) {
69
102
  return (
@@ -75,10 +108,14 @@ const ReportQuestions = ({
75
108
  />
76
109
  );
77
110
  }
111
+
78
112
  return (
79
113
  <Container>
114
+ {gradeQuestionData?.loading && <FullPageLoader fixed hasBackground />}
80
115
  {toggleGrade && (
81
116
  <GradingModal
117
+ aiValue={data?.ai_score}
118
+ setScore={handleScore}
82
119
  onClose={() => {
83
120
  setToggleGrade(false);
84
121
  }}
@@ -96,7 +133,7 @@ const ReportQuestions = ({
96
133
  <ScoreHeader>
97
134
  {accountType === "personal" ? (
98
135
  <ScoreBadge>
99
- Instructor’s score: <span>{parseInt(data?.score || 0)}%</span>
136
+ Instructor’s score: <span>{parseInt(intructorScore || 0)}%</span>
100
137
  </ScoreBadge>
101
138
  ) : (
102
139
  <>
@@ -121,7 +158,8 @@ const ReportQuestions = ({
121
158
  accountType === "instructor-affiliate"
122
159
  }
123
160
  >
124
- Instructor’s score: <span>{parseInt(data?.score || 0)}%</span>
161
+ Instructor’s score:{" "}
162
+ <span>{parseInt(intructorScore || 0)}%</span>
125
163
  </ScoreBadge>
126
164
  {(accountType === "instructor-personal" ||
127
165
  accountType === "instructor-affiliate") && (
@@ -158,7 +196,11 @@ const ReportQuestions = ({
158
196
  />
159
197
  )}
160
198
  {questionType === "essay-unscripted" && (
161
- <EssayUnscripted data={data} aiData={AiData} />
199
+ <EssayUnscripted
200
+ data={data}
201
+ aiData={AiData}
202
+ setToggle={setToggle}
203
+ />
162
204
  )}
163
205
  {questionType === "sound-play" && (
164
206
  <SoundPlay data={data} aiData={AiData} setToggle={setToggle} />
@@ -211,6 +253,9 @@ const ReportQuestions = ({
211
253
 
212
254
  <Comment
213
255
  data={comment}
256
+ testId={testId}
257
+ questionData={data}
258
+ setData={setComment}
214
259
  editMode={
215
260
  accountType === "instructor-personal" ||
216
261
  accountType === "instructor-affiliate"
@@ -219,7 +264,7 @@ const ReportQuestions = ({
219
264
  {(accountType === "instructor-personal" ||
220
265
  accountType === "instructor-affiliate") && (
221
266
  <QuestionFooter>
222
- <ButtonComponent text="Save" />
267
+ <ButtonComponent text="Save" onClick={onClose} />
223
268
  </QuestionFooter>
224
269
  )}
225
270
  </Content>