UI changes to Solutions (Writing, Speaking and Interactive Speaking) as requested

This commit is contained in:
Carlos Mesquita
2024-08-06 17:02:17 +01:00
parent a4a40b9145
commit 7fd56357e0
4 changed files with 115 additions and 132 deletions

View File

@@ -24,7 +24,7 @@ export default function InteractiveSpeaking({
onBack, onBack,
}: InteractiveSpeakingExercise & CommonProps) { }: InteractiveSpeakingExercise & CommonProps) {
const [solutionsURL, setSolutionsURL] = useState<string[]>([]); const [solutionsURL, setSolutionsURL] = useState<string[]>([]);
const [diffNumber, setDiffNumber] = useState<0 | 1 | 2 | 3>(0); const [diffNumber, setDiffNumber] = useState(0);
useEffect(() => { useEffect(() => {
if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) { if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) {
@@ -115,13 +115,13 @@ export default function InteractiveSpeaking({
{userSolutions && {userSolutions &&
userSolutions.length > 0 && userSolutions.length > 0 &&
userSolutions[0].evaluation && userSolutions[0].evaluation &&
userSolutions[0].evaluation[`transcript_${(index + 1) as 1 | 2 | 3}`] && userSolutions[0].evaluation[`transcript_${(index + 1)}`] &&
userSolutions[0].evaluation[`fixed_text_${(index + 1) as 1 | 2 | 3}`] && ( userSolutions[0].evaluation[`fixed_text_${(index + 1)}`] && (
<Button <Button
className="w-full max-w-[180px] !py-2 self-center" className="w-full max-w-[180px] !py-2 self-center"
color="pink" color="pink"
variant="outline" variant="outline"
onClick={() => setDiffNumber((index + 1) as 1 | 2 | 3)}> onClick={() => setDiffNumber((index + 1))}>
View Correction View Correction
</Button> </Button>
)} )}
@@ -144,9 +144,20 @@ export default function InteractiveSpeaking({
})} })}
</div> </div>
{userSolutions[0].evaluation && {userSolutions[0].evaluation &&
Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).length === 3 ? ( Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).length > 0 ? (
<Tab.Group> <Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1"> <Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1">
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
General Feedback
</Tab>
<Tab <Tab
className={({selected}) => className={({selected}) =>
clsx( clsx(
@@ -158,7 +169,9 @@ export default function InteractiveSpeaking({
}> }>
Evaluation Evaluation
</Tab> </Tab>
{Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).map((key, index) => (
<Tab <Tab
key={key}
className={({ selected }) => className={({ selected }) =>
clsx( clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80", "w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
@@ -167,61 +180,11 @@ export default function InteractiveSpeaking({
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking", selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
) )
}> }>
Recommended Answer (Prompt 1) Recommended Answer<br />(Prompt {index + 1})
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Recommended Answer (Prompt 2)
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Recommended Answer (Prompt 3)
</Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Global Overview
</Tab> </Tab>
))}
</Tab.List> </Tab.List>
<Tab.Panels> <Tab.Panels>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer_1!.answer.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer_2!.answer.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer_3!.answer.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4"> <Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => {
@@ -230,15 +193,25 @@ export default function InteractiveSpeaking({
return ( return (
<div key={key} className="flex flex-col gap-2"> <div key={key} className="flex flex-col gap-2">
<span className={"font-semibold"}> <div className={clsx("bg-ielts-speaking text-ielts-speaking-light rounded-xl px-4 py-2 w-fit")} key={key}>
{key}: Level {grade} {key}: Level {grade}
</span> </div>
{typeof taskResponse !== "number" && <span>{taskResponse.comment}</span>} {typeof taskResponse !== "number" && <span className="px-2 py-2">{taskResponse.comment}</span>}
</div> </div>
); );
})} })}
</div> </div>
</Tab.Panel> </Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
{Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).map((key, index) => (
<Tab.Panel key={key} className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation![`perfect_answer_${(index + 1)}`].answer.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
))}
</Tab.Panels> </Tab.Panels>
</Tab.Group> </Tab.Group>
) : ( ) : (

View File

@@ -141,6 +141,17 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
(userSolutions[0].evaluation.perfect_answer || userSolutions[0].evaluation.perfect_answer_1) ? ( (userSolutions[0].evaluation.perfect_answer || userSolutions[0].evaluation.perfect_answer_1) ? (
<Tab.Group> <Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1"> <Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1">
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
General Feedback
</Tab>
<Tab <Tab
className={({ selected }) => className={({ selected }) =>
clsx( clsx(
@@ -163,30 +174,9 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
}> }>
Recommended Answer Recommended Answer
</Tab> </Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
)
}>
Global Overview
</Tab>
</Tab.List> </Tab.List>
<Tab.Panels> <Tab.Panels>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4"> {/* General Feedback */}
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer &&
userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n")}
{userSolutions[0].evaluation!.perfect_answer_1 &&
userSolutions[0].evaluation!.perfect_answer_1.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4"> <Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => {
@@ -195,15 +185,28 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
return ( return (
<div key={key} className="flex flex-col gap-2"> <div key={key} className="flex flex-col gap-2">
<span className={"font-semibold"}> <div className={clsx("bg-ielts-speaking text-ielts-speaking-light rounded-xl px-4 py-2 w-fit")} key={key}>
{key}: Level {grade} {key}: Level {grade}
</span> </div>
{typeof taskResponse !== "number" && <span>{taskResponse.comment}</span>} {typeof taskResponse !== "number" && <span className="px-2 py-2">{taskResponse.comment}</span>}
</div> </div>
); );
})} })}
</div> </div>
</Tab.Panel> </Tab.Panel>
{/* Evaluation */}
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
{/* Recommended Answer */}
<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer &&
userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n")}
{userSolutions[0].evaluation!.perfect_answer_1 &&
userSolutions[0].evaluation!.perfect_answer_1.replaceAll(/\s{2,}/g, "\n\n")}
</span>
</Tab.Panel>
</Tab.Panels> </Tab.Panels>
</Tab.Group> </Tab.Group>
) : ( ) : (

View File

@@ -137,6 +137,17 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
{userSolutions[0].evaluation && userSolutions[0].evaluation.perfect_answer ? ( {userSolutions[0].evaluation && userSolutions[0].evaluation.perfect_answer ? (
<Tab.Group> <Tab.Group>
<Tab.List className="flex space-x-1 rounded-xl bg-ielts-writing/20 p-1"> <Tab.List className="flex space-x-1 rounded-xl bg-ielts-writing/20 p-1">
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-writing focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-writing",
)
}>
General Feedback
</Tab>
<Tab <Tab
className={({selected}) => className={({selected}) =>
clsx( clsx(
@@ -159,17 +170,6 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
}> }>
Recommended Answer Recommended Answer
</Tab> </Tab>
<Tab
className={({selected}) =>
clsx(
"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-writing/80",
"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-writing focus:outline-none focus:ring-2",
"transition duration-300 ease-in-out",
selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-writing",
)
}>
Global Overview
</Tab>
{aiEval && user?.type !== "student" && ( {aiEval && user?.type !== "student" && (
<Tab <Tab
className={({selected}) => className={({selected}) =>
@@ -185,14 +185,7 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
)} )}
</Tab.List> </Tab.List>
<Tab.Panels> <Tab.Panels>
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4"> {/* Global */}
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n").replaceAll("\\n", "\n")}
</span>
</Tab.Panel>
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4"> <Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { {Object.keys(userSolutions[0].evaluation!.task_response).map((key) => {
@@ -201,15 +194,25 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
return ( return (
<div key={key} className="flex flex-col gap-2"> <div key={key} className="flex flex-col gap-2">
<span className={"font-semibold"}> <div className={clsx("bg-ielts-writing text-ielts-writing-light rounded-xl px-4 py-2 w-fit")} key={key}>
{key}: Level {grade} {key}: Level {grade}
</span> </div>
{typeof taskResponse !== "number" && <span>{taskResponse.comment}</span>} {typeof taskResponse !== "number" && <span className="px-2 py-2">{taskResponse.comment}</span>}
</div> </div>
); );
})} })}
</div> </div>
</Tab.Panel> </Tab.Panel>
{/* Evaluation */}
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
</Tab.Panel>
{/* Recommended Answer */}
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
{userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n").replaceAll("\\n", "\n")}
</span>
</Tab.Panel>
{aiEval && user?.type !== "student" && ( {aiEval && user?.type !== "student" && (
<Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4"> <Tab.Panel className="w-full bg-ielts-writing/10 h-fit rounded-xl p-6 flex flex-col gap-4">
<AIDetection {...aiEval} /> <AIDetection {...aiEval} />

View File

@@ -115,17 +115,21 @@ export interface Evaluation {
misspelled_pairs?: {correction: string | null; misspelled: string}[]; misspelled_pairs?: {correction: string | null; misspelled: string}[];
} }
interface InteractiveSpeakingEvaluation extends Evaluation {
perfect_answer_1?: {answer: string}; type InteractivePerfectAnswerKey = `perfect_answer_${number}`;
transcript_1?: string; type InteractiveTranscriptKey = `transcript_${number}`;
fixed_text_1?: string; type InteractiveFixedTextKey = `fixed_text_${number}`;
perfect_answer_2?: {answer: string};
transcript_2?: string; type InteractivePerfectAnswerType = { [key in InteractivePerfectAnswerKey]: { answer: string } };
fixed_text_2?: string; type InteractiveTranscriptType = { [key in InteractiveTranscriptKey]?: string };
perfect_answer_3?: {answer: string}; type InteractiveFixedTextType = { [key in InteractiveFixedTextKey]?: string };
transcript_3?: string;
fixed_text_3?: string; interface InteractiveSpeakingEvaluation extends Evaluation,
} InteractivePerfectAnswerType,
InteractiveTranscriptType,
InteractiveFixedTextType
{}
interface SpeakingEvaluation extends CommonEvaluation { interface SpeakingEvaluation extends CommonEvaluation {
perfect_answer_1?: string; perfect_answer_1?: string;