l-min-components 1.7.1414 → 1.7.1415

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.1414",
3
+ "version": "1.7.1415",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/assets",
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+
3
+ const WarningGrey = () => {
4
+ return (
5
+ <svg
6
+ width="20"
7
+ height="20"
8
+ viewBox="0 0 20 20"
9
+ fill="none"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ >
12
+ <path
13
+ d="M9 5H11V7H9V5ZM9 9H11V15H9V9ZM10 0C4.48 0 0 4.48 0 10C0 15.52 4.48 20 10 20C15.52 20 20 15.52 20 10C20 4.48 15.52 0 10 0ZM10 18C5.59 18 2 14.41 2 10C2 5.59 5.59 2 10 2C14.41 2 18 5.59 18 10C18 14.41 14.41 18 10 18Z"
14
+ fill="#949999"
15
+ />
16
+ </svg>
17
+ );
18
+ };
19
+
20
+ export default WarningGrey;
@@ -16,7 +16,7 @@ const EvalutionFeedback = ({
16
16
  {!hideWarning && (
17
17
  <div>
18
18
  <WarningIcon />
19
- <p>Introduced words are highlighted in blue</p>
19
+ <p>Introduced words are highlighted in green</p>
20
20
  </div>
21
21
  )}
22
22
  </Header>
@@ -62,6 +62,6 @@ const Header = styled.div`
62
62
  export const HighlightedText = styled.p`
63
63
  font-size: 14px;
64
64
  span {
65
- color: #00c2c2;
65
+ color: #30d468;
66
66
  }
67
67
  `;
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useEffect } from "react";
2
2
  import {
3
3
  GrammarContent,
4
4
  GrammarHeader,
@@ -14,35 +14,36 @@ import { MarsIcon } from "lucide-react";
14
14
  import { useState } from "react";
15
15
  import GoodCheck from "../../../../assets/svg/goodCheck";
16
16
  import RedX from "../../../../assets/svg/redX";
17
+ import useReportUtils from "../../hooks/useRreportUtils";
18
+ import WarningGrey from "../../../../assets/svg/warningGrey";
17
19
 
18
- const Grammar = () => {
20
+ const Grammar = ({ Aidata }) => {
19
21
  const [selectedSection, setSelectedSection] = useState(1);
20
- const sampleText =
21
- "Text <span><span>1</span>setup</span> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Veritatis odio laboriosam adipisci ab inventore velit pariatur, alias quas hic libero.";
22
+ const [selectedWord, setSelectedWord] = useState(null);
22
23
 
23
- const texts = [
24
- { text: "Hello" },
25
- { text: "world,", position: 1 },
26
- { text: "James", position: 2 },
27
- { text: "back" },
28
- { text: "How" },
29
- { text: "are", position: 3 },
30
- { text: "you" },
31
- { text: "doing", position: 4 },
32
- { text: "today?" },
33
- { text: "It's", position: 5 },
34
- { text: "been" },
35
- { text: "a" },
36
- { text: "while", position: 6 },
37
- { text: "since" },
38
- { text: "we", position: 7 },
39
- { text: "last" },
40
- { text: "met.", position: 8 },
41
- { text: "Hope" },
42
- { text: "everything", position: 9 },
43
- { text: "is" },
44
- { text: "great!" },
45
- ];
24
+ const data = Aidata?.data;
25
+ const feedbackCorrection = data?.["Correction Operations (Optional)"] || [];
26
+ const originalText = data?.["Original Speech"] || "";
27
+ const correctText = data?.["Grammatical Correct Version"] || "";
28
+ const feedbacks = data?.["Feedback"];
29
+ const {
30
+ grammarFeekbackResult,
31
+ grammerCorrectParagraph,
32
+ grammarCorrectResult,
33
+ } = useReportUtils();
34
+
35
+ const wordsFeedback = grammarFeekbackResult(
36
+ originalText,
37
+ feedbackCorrection,
38
+ feedbacks
39
+ );
40
+ const correctWods = grammarCorrectResult(correctText, feedbackCorrection);
41
+ const correctParagraph = correctWods
42
+ ? grammerCorrectParagraph(correctWods)
43
+ : "";
44
+ useEffect(() => {
45
+ if (wordsFeedback?.length) setSelectedWord(wordsFeedback?.[0]);
46
+ }, [wordsFeedback?.length]);
46
47
 
47
48
  const tabs = [
48
49
  { label: "Feedback", value: 1, icon: ChatIcon },
@@ -58,13 +59,18 @@ const Grammar = () => {
58
59
  <p>Click on the words to see detailed feedback</p>
59
60
  </div>
60
61
  <GrammarHeaderContent>
61
- {texts?.map((item, idx) => (
62
+ {wordsFeedback?.map((word, idx) => (
62
63
  <span
63
- className={classNames({ "error-text": item?.position })}
64
+ className={classNames({ "error-text": word?.position })}
64
65
  key={idx}
66
+ onClick={() => {
67
+ setSelectedWord(word);
68
+
69
+ setSelectedSection(1);
70
+ }}
65
71
  >
66
- {item?.position && <span>{item.position}</span>}
67
- {item.text}
72
+ {word?.position && <span>{word?.position}</span>}
73
+ {word?.text}
68
74
  </span>
69
75
  ))}
70
76
  </GrammarHeaderContent>
@@ -76,7 +82,9 @@ const Grammar = () => {
76
82
  className={classNames({
77
83
  active: selectedSection === tab.value,
78
84
  })}
79
- onClick={() => setSelectedSection(tab.value)}
85
+ onClick={() => {
86
+ setSelectedSection(tab.value);
87
+ }}
80
88
  >
81
89
  <tab.icon
82
90
  color={selectedSection === tab.value ? "#f5f7f7" : "#949999"}
@@ -87,26 +95,30 @@ const Grammar = () => {
87
95
  </ul>
88
96
  </GrammarHeader>
89
97
  <GrammarContent>
90
- {selectedSection === 1 && (
98
+ {selectedSection === 1 && selectedWord && (
91
99
  <div className="feedback_section">
92
100
  <div className="failed">
93
101
  <RedX />
94
102
  <span>
95
- <span>1</span> Makes
103
+ <span>{selectedWord?.position}</span> {selectedWord?.text}
96
104
  </span>
97
105
  </div>
98
106
  <div className="correct">
99
107
  <GoodCheck />
100
- <span>Makes</span>
108
+ <span>{selectedWord?.correct}</span>
101
109
  </div>
102
- <p>
103
- The verbs should be in the same tense within the a sentence or
104
- paragraph
105
- </p>
110
+ <p>{selectedWord?.feedback}</p>
106
111
  </div>
107
112
  )}
108
- {selectedSection === 2 && (
109
- <p>Technology make more convenient life and means easier.</p>
113
+ {selectedSection === 2 && originalText && <p>{originalText}</p>}
114
+ {selectedSection === 3 && (
115
+ <div className="correct_section">
116
+ <div className="warning">
117
+ <WarningGrey />
118
+ <p>Introduced words are highlighted in green</p>
119
+ </div>
120
+ <p dangerouslySetInnerHTML={{ __html: correctParagraph }}></p>
121
+ </div>
110
122
  )}
111
123
  </GrammarContent>
112
124
  </ModelContent>
@@ -72,7 +72,7 @@ const SpeechAnalysis = ({ Aidata, isPersonal }) => {
72
72
  <HandIcon />
73
73
  <p>Click on the words to see detailed feedback</p>
74
74
  </div>
75
- {true && (
75
+ {isPersonal && (
76
76
  <div className="">
77
77
  <PlayButton audio={Aidata?.audioData} />
78
78
  <PlayButton type="ai" refernceText={Aidata?.data?.Reference} />
@@ -53,9 +53,11 @@ const FullAnalysis = ({ data, onClose, accountType }) => {
53
53
  };
54
54
  }, []);
55
55
 
56
- const firstModel = data && data?.models?.[0];
57
- const secondModel = data && data?.models?.[1];
58
- const thirdModel = data && data?.models?.[2];
56
+ const sideModels = data && data?.models?.filter((item) => item?.sideProgress);
57
+
58
+ const firstModel = sideModels && sideModels?.[0];
59
+ const secondModel = sideModels && sideModels?.[1];
60
+ const thirdModel = sideModels && sideModels?.[2];
59
61
 
60
62
  const selectedModel =
61
63
  data && data?.models?.find((item) => item?.id === selected);
@@ -74,8 +76,8 @@ const FullAnalysis = ({ data, onClose, accountType }) => {
74
76
  <ArrowLeft />
75
77
  <h1>Full analysis</h1>
76
78
  </Header>
77
- <Content className={classNames({ personal: true })}>
78
- {null && (
79
+ <Content className={classNames({ personal: accountType === "personal" })}>
80
+ {accountType !== "personal" && (
79
81
  <Sidebar>
80
82
  <ProgressSidebar>
81
83
  <ProgressCircleSection>
@@ -177,7 +179,9 @@ const FullAnalysis = ({ data, onClose, accountType }) => {
177
179
  isPersonal={accountType === "personal"}
178
180
  />
179
181
  )}
180
- {selectedModel?.id === "gammar" && <Grammar />}
182
+ {selectedModel?.id === "grammar" && (
183
+ <Grammar Aidata={selectedModel} />
184
+ )}
181
185
  </MainSection>
182
186
  </Content>
183
187
  </Container>
@@ -442,6 +442,27 @@ export const GrammarContent = styled.div`
442
442
  p {
443
443
  color: #4a4d4d;
444
444
  }
445
+
446
+ .correct_section {
447
+ > .warning {
448
+ display: flex;
449
+ align-items: center;
450
+ border-radius: 20px;
451
+ background: #fff;
452
+ width: 100%;
453
+ height: 40px;
454
+ gap: 8px;
455
+ padding: 0 20px;
456
+ color: #7c8080;
457
+ font-size: 14px;
458
+ margin-bottom: 20px;
459
+ }
460
+ p {
461
+ span {
462
+ color: #30d468;
463
+ }
464
+ }
465
+ }
445
466
  .feedback_section {
446
467
  display: flex;
447
468
  flex-direction: column;
@@ -315,8 +315,7 @@ const setupAnalysis = (data, audioData, score) => {
315
315
  if (
316
316
  data?.grammar &&
317
317
  data?.grammar?.length &&
318
- data?.grammar?.[0]?.model_data?.["Original Speech"] &&
319
- null
318
+ data?.grammar?.[0]?.model_data?.["Original Speech"]
320
319
  ) {
321
320
  const grammarData = data?.grammar?.[0]?.model_data;
322
321
  const score = grammarData?.["Grammar Score"] || 0;
@@ -394,6 +393,124 @@ const dialpgueSelectedModel = (response, aiData) => {
394
393
 
395
394
  return objectData;
396
395
  };
396
+
397
+ const grammarFeekbackResult = (originalText, feedbackCorrection, feedbacks) => {
398
+ if (!originalText || !feedbackCorrection) return;
399
+ const result = [];
400
+ let positionCounter = 1; // Tracks the word position in the text
401
+ let correctionIndex = 0; // Tracks the current correction
402
+ let words = originalText?.split(/\s+/) || []; // Split text into words
403
+ let wordIndex = 0; // Tracks the current word being processed
404
+
405
+ while (wordIndex <= words?.length) {
406
+ const word = words[wordIndex];
407
+ const correction = feedbackCorrection[correctionIndex];
408
+
409
+ if (
410
+ correction &&
411
+ (correction?.operation === "substituted" ||
412
+ correction?.operation === "formatting") && // Handle substitution
413
+ words
414
+ .slice(
415
+ wordIndex,
416
+ wordIndex + correction?.original_word.split(" ").length
417
+ )
418
+ .join(" ") === correction?.original_word
419
+ ) {
420
+ const getFeebackText = (idx) => {
421
+ if (feedbacks?.length) {
422
+ return feedbacks?.[idx] || null;
423
+ }
424
+ return null;
425
+ };
426
+ result.push({
427
+ text: correction?.original_word,
428
+ correct: correction?.replacement_word,
429
+ position: positionCounter,
430
+ operation: correction?.operation,
431
+ feedback: getFeebackText(positionCounter - 1),
432
+ });
433
+ wordIndex += correction?.original_word.split(" ").length || 0;
434
+ correctionIndex++;
435
+ positionCounter++;
436
+ } else if (correction && correction?.operation === "inserted") {
437
+ result.push({
438
+ text: correction?.word,
439
+ correct: correction?.word, // Insert the new word
440
+ position: positionCounter,
441
+ operation: correction?.operation,
442
+ });
443
+ correctionIndex++;
444
+ positionCounter++;
445
+ } else {
446
+ if (word !== undefined) {
447
+ result.push({ text: word });
448
+ }
449
+ wordIndex++;
450
+ }
451
+ }
452
+
453
+ return result;
454
+ };
455
+
456
+ const grammarCorrectResult = (correctText, feedbackCorrection) => {
457
+ if (!correctText || !feedbackCorrection) return;
458
+ const result = [];
459
+ let correctionIndex = 0;
460
+ let words = correctText.split(/\s+/);
461
+ let wordIndex = 0;
462
+
463
+ while (wordIndex < words.length) {
464
+ const word = words[wordIndex];
465
+ const correction = feedbackCorrection[correctionIndex];
466
+ if (
467
+ correction &&
468
+ (correction?.operation === "substituted" ||
469
+ correction?.operation === "formatting") &&
470
+ words
471
+ .slice(
472
+ wordIndex,
473
+ wordIndex + correction?.replacement_word.split(" ").length
474
+ )
475
+ .join(" ") === correction?.replacement_word
476
+ ) {
477
+ result.push({
478
+ text: correction?.replacement_word,
479
+ highlight: true,
480
+ });
481
+ wordIndex += correction?.replacement_word.split(" ").length;
482
+ correctionIndex++;
483
+ } else if (correction && correction?.operation === "inserted") {
484
+ result.push({
485
+ text: correction?.word,
486
+ highlight: true,
487
+ });
488
+ correctionIndex++;
489
+ } else {
490
+ result.push({ text: word });
491
+ wordIndex++;
492
+ }
493
+ }
494
+
495
+ return result;
496
+ };
497
+
498
+ const grammerCorrectParagraph = (data) => {
499
+ if (!data) return;
500
+ let paragraph = "";
501
+
502
+ data?.forEach((item) => {
503
+ if (item?.highlight) {
504
+ paragraph += `<span>${item?.text}</span> `;
505
+ } else {
506
+ paragraph += `${item?.text} `;
507
+ }
508
+ });
509
+
510
+ paragraph = paragraph?.trim();
511
+
512
+ return paragraph;
513
+ };
397
514
  const useReportUtils = () => {
398
515
  return {
399
516
  choiceListAndAnswer,
@@ -404,6 +521,9 @@ const useReportUtils = () => {
404
521
  getTrabScriptData,
405
522
  quixSelectedModel,
406
523
  dialpgueSelectedModel,
524
+ grammarFeekbackResult,
525
+ grammarCorrectResult,
526
+ grammerCorrectParagraph,
407
527
  };
408
528
  };
409
529
 
@@ -4,19 +4,33 @@ import styled from "styled-components";
4
4
  import Radio from "../radio";
5
5
  import ButtonComponent from "../../../../button";
6
6
 
7
- const GradingModal = ({ aiValue, onClose, setScore, noAi, defaultScore }) => {
7
+ const GradingModal = ({
8
+ aiValue,
9
+ onClose,
10
+ setScore,
11
+ noAi,
12
+ defaultScore,
13
+ suggestionValue,
14
+ }) => {
8
15
  const [selected, setSelected] = useState("manually");
9
16
  const [value, setValue] = useState(defaultScore || "");
10
17
 
11
18
  const numberValue = Number(value || 0);
12
19
  const disable = selected === "manually" && (numberValue > 100 || !value);
13
20
 
14
- const isNumbter = typeof aiValue === "number";
21
+ const isNumbter = Number(aiValue) || 0;
22
+ const isSuggestionNumber = Number(suggestionValue) || 0;
15
23
 
16
24
  const handleSetValue = () => {
17
25
  setScore?.({
18
- score_method: selected === "manually" ? "MANUAL" : "AI",
19
- score: selected === "manually" ? numberValue : aiValue,
26
+ score_method:
27
+ selected === "manually" || selected === "suggest" ? "MANUAL" : "AI",
28
+ score:
29
+ selected === "manually"
30
+ ? numberValue
31
+ : selected === "suggest"
32
+ ? isSuggestionNumber
33
+ : aiValue,
20
34
  });
21
35
  };
22
36
 
@@ -30,7 +44,7 @@ const GradingModal = ({ aiValue, onClose, setScore, noAi, defaultScore }) => {
30
44
  <TopSection>
31
45
  <h3>Instructor’s grading</h3>
32
46
  <ul className="check_wrapper">
33
- {isNumbter && !noAi && (
47
+ {!noAi && (
34
48
  <li
35
49
  onClick={() => {
36
50
  setSelected("ai");
@@ -43,6 +57,19 @@ const GradingModal = ({ aiValue, onClose, setScore, noAi, defaultScore }) => {
43
57
  Use AI grade
44
58
  </li>
45
59
  )}
60
+ {noAi && (
61
+ <li
62
+ onClick={() => {
63
+ setSelected("suggest");
64
+ }}
65
+ >
66
+ <Radio
67
+ checked={selected === "suggest"}
68
+ defaultBorderColor={"#C6CCCC"}
69
+ />
70
+ Use system grade
71
+ </li>
72
+ )}
46
73
  <li
47
74
  onClick={() => {
48
75
  setSelected("manually");
@@ -57,8 +84,9 @@ const GradingModal = ({ aiValue, onClose, setScore, noAi, defaultScore }) => {
57
84
  </ul>
58
85
  <div className="value_section">
59
86
  <p className="label">Grade</p>
60
- {selected === "ai" && (
61
- <p className="ai_value">{aiValue ? aiValue : 0}</p>
87
+ {selected === "ai" && <p className="ai_value">{isNumbter}</p>}
88
+ {selected === "suggest" && (
89
+ <p className="ai_value">{isSuggestionNumber}</p>
62
90
  )}
63
91
  {selected === "manually" && (
64
92
  <input
@@ -113,15 +113,18 @@ const ReportQuestions = ({
113
113
  questionType === "match-pair" ||
114
114
  questionType === "quiz-multiple-choice" ||
115
115
  questionType === "word-play-text" ||
116
- questionType === "word-play-multiple-choice" ||
117
- questionType === "essay-written";
116
+ questionType === "word-play-multiple-choice";
117
+
118
+ console.log(data);
119
+
118
120
  return (
119
121
  <Container>
120
122
  {gradeQuestionData?.loading && <FullPageLoader fixed hasBackground />}
121
123
  {toggleGrade && (
122
124
  <GradingModal
123
125
  aiValue={data?.ai_score}
124
- noAi
126
+ suggestionValue={data?.suggested_score}
127
+ noAi={noAi}
125
128
  setScore={handleScore}
126
129
  defaultScore={intructorScore}
127
130
  onClose={() => {
@@ -145,16 +148,14 @@ const ReportQuestions = ({
145
148
  </ScoreBadge>
146
149
  ) : (
147
150
  <>
148
- {null && (
149
- <ScoreBadge
150
- ai
151
- className={classNames({
152
- hidden: noAi,
153
- })}
154
- >
155
- AI score: <span>{parseInt(data?.ai_score || 0)}%</span>
156
- </ScoreBadge>
157
- )}
151
+ <ScoreBadge
152
+ ai
153
+ className={classNames({
154
+ hidden: noAi,
155
+ })}
156
+ >
157
+ AI score: <span>{parseInt(data?.ai_score || 0)}%</span>
158
+ </ScoreBadge>
158
159
  <ScoreRight>
159
160
  <></>
160
161
  <ScoreBadge