Merge branch 'develop'
This commit is contained in:
@@ -132,7 +132,14 @@ export default function Writing({
|
|||||||
<Button
|
<Button
|
||||||
color="purple"
|
color="purple"
|
||||||
disabled={!isSubmitEnabled}
|
disabled={!isSubmitEnabled}
|
||||||
onClick={() => onNext({exercise: id, solutions: [{id, solution: inputText}], score: {correct: 1, total: 1, missing: 0}, type})}
|
onClick={() =>
|
||||||
|
onNext({
|
||||||
|
exercise: id,
|
||||||
|
solutions: [{id, solution: inputText.replaceAll(/\s{2,}/g, " ")}],
|
||||||
|
score: {correct: 1, total: 1, missing: 0},
|
||||||
|
type,
|
||||||
|
})
|
||||||
|
}
|
||||||
className="max-w-[200px] self-end w-full">
|
className="max-w-[200px] self-end w-full">
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default function InteractiveSpeaking({
|
|||||||
const [diffNumber, setDiffNumber] = useState<0 | 1 | 2 | 3>(0);
|
const [diffNumber, setDiffNumber] = useState<0 | 1 | 2 | 3>(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userSolutions && userSolutions.length > 0) {
|
if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) {
|
||||||
Promise.all(userSolutions[0].solution.map((x) => axios.post(`/api/speaking`, {path: x.answer}, {responseType: "arraybuffer"}))).then(
|
Promise.all(userSolutions[0].solution.map((x) => axios.post(`/api/speaking`, {path: x.answer}, {responseType: "arraybuffer"}))).then(
|
||||||
(values) => {
|
(values) => {
|
||||||
setSolutionsURL(
|
setSolutionsURL(
|
||||||
@@ -239,7 +239,11 @@ export default function InteractiveSpeaking({
|
|||||||
onNext({
|
onNext({
|
||||||
exercise: id,
|
exercise: id,
|
||||||
solutions: userSolutions,
|
solutions: userSolutions,
|
||||||
score: {total: 100, missing: 0, correct: speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0},
|
score: {
|
||||||
|
total: 100,
|
||||||
|
missing: 0,
|
||||||
|
correct: userSolutions[0]?.evaluation ? speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0 : 0,
|
||||||
|
},
|
||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
|
|||||||
const [showDiff, setShowDiff] = useState(false);
|
const [showDiff, setShowDiff] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userSolutions && userSolutions.length > 0) {
|
if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) {
|
||||||
axios.post(`/api/speaking`, {path: userSolutions[0].solution}, {responseType: "arraybuffer"}).then(({data}) => {
|
axios.post(`/api/speaking`, {path: userSolutions[0].solution}, {responseType: "arraybuffer"}).then(({data}) => {
|
||||||
const blob = new Blob([data], {type: "audio/wav"});
|
const blob = new Blob([data], {type: "audio/wav"});
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
@@ -29,10 +29,6 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
|
|||||||
}
|
}
|
||||||
}, [userSolutions]);
|
}, [userSolutions]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(userSolutions);
|
|
||||||
}, [userSolutions]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal title="Correction" isOpen={showDiff} onClose={() => setShowDiff(false)}>
|
<Modal title="Correction" isOpen={showDiff} onClose={() => setShowDiff(false)}>
|
||||||
@@ -205,7 +201,11 @@ export default function Speaking({id, type, title, video_url, text, prompts, use
|
|||||||
onNext({
|
onNext({
|
||||||
exercise: id,
|
exercise: id,
|
||||||
solutions: userSolutions,
|
solutions: userSolutions,
|
||||||
score: {total: 100, missing: 0, correct: speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0},
|
score: {
|
||||||
|
total: 100,
|
||||||
|
missing: 0,
|
||||||
|
correct: userSolutions[0]?.evaluation ? speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0 : 0,
|
||||||
|
},
|
||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{showDiff && (
|
{showDiff && userSolutions[0].evaluation && (
|
||||||
<>
|
<>
|
||||||
<span>Correction:</span>
|
<span>Correction:</span>
|
||||||
<div className="w-full h-full max-h-[320px] overflow-y-scroll scrollbar-hide cursor-text border-2 overflow-x-hidden border-mti-gray-platinum bg-white rounded-3xl">
|
<div className="w-full h-full max-h-[320px] overflow-y-scroll scrollbar-hide cursor-text border-2 overflow-x-hidden border-mti-gray-platinum bg-white rounded-3xl">
|
||||||
@@ -191,7 +191,11 @@ export default function Writing({id, type, prompt, attachment, userSolutions, on
|
|||||||
onNext({
|
onNext({
|
||||||
exercise: id,
|
exercise: id,
|
||||||
solutions: userSolutions,
|
solutions: userSolutions,
|
||||||
score: {total: 100, missing: 0, correct: writingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0},
|
score: {
|
||||||
|
total: 100,
|
||||||
|
missing: 0,
|
||||||
|
correct: userSolutions[0]?.evaluation ? writingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0 : 0,
|
||||||
|
},
|
||||||
type,
|
type,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {toast} from "react-toastify";
|
|||||||
import {uuidv4} from "@firebase/util";
|
import {uuidv4} from "@firebase/util";
|
||||||
import {Assignment} from "@/interfaces/results";
|
import {Assignment} from "@/interfaces/results";
|
||||||
import Checkbox from "@/components/Low/Checkbox";
|
import Checkbox from "@/components/Low/Checkbox";
|
||||||
|
import {Variant} from "@/interfaces/exam";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isCreating: boolean;
|
isCreating: boolean;
|
||||||
@@ -38,6 +39,7 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
|
|||||||
const [endDate, setEndDate] = useState<Date | null>(
|
const [endDate, setEndDate] = useState<Date | null>(
|
||||||
assignment ? moment(assignment.endDate).toDate() : moment().hours(23).minutes(59).add(8, "day").toDate(),
|
assignment ? moment(assignment.endDate).toDate() : moment().hours(23).minutes(59).add(8, "day").toDate(),
|
||||||
);
|
);
|
||||||
|
const [variant, setVariant] = useState<Variant>("full");
|
||||||
// creates a new exam for each assignee or just one exam for all assignees
|
// creates a new exam for each assignee or just one exam for all assignees
|
||||||
const [generateMultiple, setGenerateMultiple] = useState<boolean>(false);
|
const [generateMultiple, setGenerateMultiple] = useState<boolean>(false);
|
||||||
|
|
||||||
@@ -60,6 +62,7 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
|
|||||||
endDate,
|
endDate,
|
||||||
selectedModules,
|
selectedModules,
|
||||||
generateMultiple,
|
generateMultiple,
|
||||||
|
variant,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
toast.success(`The assignment "${name}" has been ${assignment ? "updated" : "created"} successfully!`);
|
toast.success(`The assignment "${name}" has been ${assignment ? "updated" : "created"} successfully!`);
|
||||||
@@ -279,7 +282,10 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div className="flex gap-4 w-full justify-end">
|
<div className="flex flex-col gap-4 w-full items-end">
|
||||||
|
<Checkbox isChecked={variant === "full"} onChange={() => setVariant((prev) => (prev === "full" ? "partial" : "full"))}>
|
||||||
|
Full length exams
|
||||||
|
</Checkbox>
|
||||||
<Checkbox isChecked={generateMultiple} onChange={() => setGenerateMultiple((d) => !d)}>
|
<Checkbox isChecked={generateMultiple} onChange={() => setGenerateMultiple((d) => !d)}>
|
||||||
Generate different exams
|
Generate different exams
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {Module} from ".";
|
import {Module} from ".";
|
||||||
|
|
||||||
export type Exam = ReadingExam | ListeningExam | WritingExam | SpeakingExam | LevelExam;
|
export type Exam = ReadingExam | ListeningExam | WritingExam | SpeakingExam | LevelExam;
|
||||||
export type Variant = "full" | "diagnostic" | "partial";
|
export type Variant = "full" | "partial";
|
||||||
|
|
||||||
export interface ReadingExam {
|
export interface ReadingExam {
|
||||||
parts: ReadingPart[];
|
parts: ReadingPart[];
|
||||||
|
|||||||
@@ -58,45 +58,59 @@ export default function BatchCodeGenerator({user}: {user: User}) {
|
|||||||
if (filesContent.length > 0) {
|
if (filesContent.length > 0) {
|
||||||
const file = filesContent[0];
|
const file = filesContent[0];
|
||||||
readXlsxFile(file.content).then((rows) => {
|
readXlsxFile(file.content).then((rows) => {
|
||||||
const information = uniqBy(
|
try {
|
||||||
rows
|
const information = uniqBy(
|
||||||
.map((row) => {
|
rows
|
||||||
const [firstName, lastName, country, passport_id, email, phone] = row as string[];
|
.map((row) => {
|
||||||
return EMAIL_REGEX.test(email) && !users.map((u) => u.email).includes(email)
|
const [firstName, lastName, country, passport_id, email, ...phone] = row as string[];
|
||||||
? {
|
return EMAIL_REGEX.test(email.toString().trim()) && !users.map((u) => u.email).includes(email.toString().trim())
|
||||||
email: email.toString(),
|
? {
|
||||||
name: `${firstName ?? ""} ${lastName ?? ""}`.trim(),
|
email: email.toString().trim(),
|
||||||
passport_id: passport_id.toString(),
|
name: `${firstName ?? ""} ${lastName ?? ""}`.trim(),
|
||||||
}
|
passport_id: passport_id?.toString().trim() || undefined,
|
||||||
: undefined;
|
}
|
||||||
})
|
: undefined;
|
||||||
.filter((x) => !!x) as typeof infos,
|
})
|
||||||
(x) => x.email,
|
.filter((x) => !!x) as typeof infos,
|
||||||
);
|
(x) => x.email,
|
||||||
|
);
|
||||||
|
|
||||||
if (information.length === 0) {
|
if (information.length === 0) {
|
||||||
|
toast.error(
|
||||||
|
"Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!",
|
||||||
|
);
|
||||||
|
return clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
setInfos(information);
|
||||||
|
} catch {
|
||||||
toast.error(
|
toast.error(
|
||||||
"Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!",
|
"Please upload an Excel file containing user information, one per line! All already registered e-mails have also been ignored!",
|
||||||
);
|
);
|
||||||
return clear();
|
return clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
setInfos(information);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [filesContent]);
|
}, [filesContent]);
|
||||||
|
|
||||||
const generateCode = (type: Type) => {
|
const generateCode = (type: Type) => {
|
||||||
|
if (!confirm(`You are about to generate ${infos.length} codes, are you sure you want to continue?`)) return;
|
||||||
|
|
||||||
const uid = new ShortUniqueId();
|
const uid = new ShortUniqueId();
|
||||||
const codes = infos.map(() => uid.randomUUID(6));
|
const codes = infos.map(() => uid.randomUUID(6));
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
axios
|
axios
|
||||||
.post("/api/code", {type, codes, infos: infos, expiryDate})
|
.post<{ok: boolean; valid?: number; reason?: string}>("/api/code", {type, codes, infos: infos, expiryDate})
|
||||||
.then(({data, status}) => {
|
.then(({data, status}) => {
|
||||||
if (data.ok) {
|
if (data.ok) {
|
||||||
toast.success(`Successfully generated ${capitalize(type)} codes and they have been notified by e-mail!`, {toastId: "success"});
|
toast.success(
|
||||||
|
`Successfully generated${data.valid ? ` ${data.valid}/${infos.length}` : ""} ${capitalize(
|
||||||
|
type,
|
||||||
|
)} codes and they have been notified by e-mail!`,
|
||||||
|
{toastId: "success"},
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +126,10 @@ export default function BatchCodeGenerator({user}: {user: User}) {
|
|||||||
|
|
||||||
toast.error(`Something went wrong, please try again later!`, {toastId: "error"});
|
toast.error(`Something went wrong, please try again later!`, {toastId: "error"});
|
||||||
})
|
})
|
||||||
.finally(() => setIsLoading(false));
|
.finally(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
return clear();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {sessionOptions} from "@/lib/session";
|
|||||||
import {uuidv4} from "@firebase/util";
|
import {uuidv4} from "@firebase/util";
|
||||||
import {Module} from "@/interfaces";
|
import {Module} from "@/interfaces";
|
||||||
import {getExams} from "@/utils/exams.be";
|
import {getExams} from "@/utils/exams.be";
|
||||||
import {Exam} from "@/interfaces/exam";
|
import {Exam, Variant} from "@/interfaces/exam";
|
||||||
import {capitalize, flatten} from "lodash";
|
import {capitalize, flatten} from "lodash";
|
||||||
import {User} from "@/interfaces/user";
|
import {User} from "@/interfaces/user";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
@@ -52,13 +52,18 @@ function getRandomIndex(arr: any[]): number {
|
|||||||
return randomIndex;
|
return randomIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
const generateExams = async (generateMultiple: Boolean, selectedModules: Module[], assignees: string[]): Promise<ExamWithUser[]> => {
|
const generateExams = async (
|
||||||
|
generateMultiple: Boolean,
|
||||||
|
selectedModules: Module[],
|
||||||
|
assignees: string[],
|
||||||
|
variant?: Variant,
|
||||||
|
): Promise<ExamWithUser[]> => {
|
||||||
if (generateMultiple) {
|
if (generateMultiple) {
|
||||||
// for optimization purposes, it would be better to create a new endpoint that returned the answers for all users at once
|
// for optimization purposes, it would be better to create a new endpoint that returned the answers for all users at once
|
||||||
const allExams = await assignees.map(async (assignee) => {
|
const allExams = await assignees.map(async (assignee) => {
|
||||||
const selectedModulePromises = await selectedModules.map(async (module: Module) => {
|
const selectedModulePromises = await selectedModules.map(async (module: Module) => {
|
||||||
try {
|
try {
|
||||||
const exams: Exam[] = await getExams(db, module, "true", assignee);
|
const exams: Exam[] = await getExams(db, module, "true", assignee, variant);
|
||||||
|
|
||||||
const exam = exams[getRandomIndex(exams)];
|
const exam = exams[getRandomIndex(exams)];
|
||||||
if (exam) {
|
if (exam) {
|
||||||
@@ -101,6 +106,7 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
// Generate multiple true would generate an unique exam for each user
|
// Generate multiple true would generate an unique exam for each user
|
||||||
// false would generate the same exam for all users
|
// false would generate the same exam for all users
|
||||||
generateMultiple = false,
|
generateMultiple = false,
|
||||||
|
variant,
|
||||||
...body
|
...body
|
||||||
} = req.body as {
|
} = req.body as {
|
||||||
selectedModules: Module[];
|
selectedModules: Module[];
|
||||||
@@ -109,9 +115,10 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
name: string;
|
name: string;
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
|
variant?: Variant;
|
||||||
};
|
};
|
||||||
|
|
||||||
const exams: ExamWithUser[] = await generateExams(generateMultiple, selectedModules, assignees);
|
const exams: ExamWithUser[] = await generateExams(generateMultiple, selectedModules, assignees, variant);
|
||||||
|
|
||||||
if (exams.length === 0) {
|
if (exams.length === 0) {
|
||||||
res.status(400).json({ok: false, error: "No exams found for the selected modules"});
|
res.status(400).json({ok: false, error: "No exams found for the selected modules"});
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const {type, codes, infos, expiryDate} = req.body as {
|
const {type, codes, infos, expiryDate} = req.body as {
|
||||||
type: Type;
|
type: Type;
|
||||||
codes: string[];
|
codes: string[];
|
||||||
infos?: {email: string; name: string; passport_id: string}[];
|
infos?: {email: string; name: string; passport_id?: string}[];
|
||||||
expiryDate: null | Date;
|
expiryDate: null | Date;
|
||||||
};
|
};
|
||||||
const permission = PERMISSIONS.generateCode[type];
|
const permission = PERMISSIONS.generateCode[type];
|
||||||
@@ -70,11 +70,10 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
|
|
||||||
const codePromises = codes.map(async (code, index) => {
|
const codePromises = codes.map(async (code, index) => {
|
||||||
const codeRef = doc(db, "codes", code);
|
const codeRef = doc(db, "codes", code);
|
||||||
await setDoc(codeRef, {type, code, creator: req.session.user!.id, expiryDate});
|
const codeInformation = {type, code, creator: req.session.user!.id, expiryDate};
|
||||||
|
|
||||||
if (infos && infos.length > index) {
|
if (infos && infos.length > index) {
|
||||||
const {email, name, passport_id} = infos[index];
|
const {email, name, passport_id} = infos[index];
|
||||||
await setDoc(codeRef, {email: email.trim(), name: name.trim(), passport_id: passport_id.trim()}, {merge: true});
|
|
||||||
|
|
||||||
const transport = prepareMailer();
|
const transport = prepareMailer();
|
||||||
const mailOptions = prepareMailOptions(
|
const mailOptions = prepareMailOptions(
|
||||||
@@ -87,11 +86,24 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
"main",
|
"main",
|
||||||
);
|
);
|
||||||
|
|
||||||
await transport.sendMail(mailOptions);
|
try {
|
||||||
|
await transport.sendMail(mailOptions);
|
||||||
|
await setDoc(
|
||||||
|
codeRef,
|
||||||
|
{...codeInformation, email: email.trim(), name: name.trim(), ...(passport_id ? {passport_id: passport_id.trim()} : {})},
|
||||||
|
{merge: true},
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await setDoc(codeRef, codeInformation);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(codePromises).then(() => {
|
Promise.all(codePromises).then((results) => {
|
||||||
res.status(200).json({ok: true});
|
res.status(200).json({ok: true, valid: results.filter((x) => x).length});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
|
||||||
import type {NextApiRequest, NextApiResponse} from "next";
|
|
||||||
import {app} from "@/firebase";
|
|
||||||
import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc, deleteDoc} from "firebase/firestore";
|
|
||||||
import {withIronSessionApiRoute} from "iron-session/next";
|
|
||||||
import {sessionOptions} from "@/lib/session";
|
|
||||||
import {uuidv4} from "@firebase/util";
|
|
||||||
|
|
||||||
const db = getFirestore(app);
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
if (req.method === "GET") return GET(req, res);
|
|
||||||
|
|
||||||
res.status(404).json({ok: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function GET(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
const {id} = req.query;
|
|
||||||
|
|
||||||
const snapshot = await getDoc(doc(db, "stats", id as string));
|
|
||||||
|
|
||||||
res.status(200).json({...snapshot.data(), id: snapshot.id});
|
|
||||||
}
|
|
||||||
@@ -30,6 +30,9 @@ import AgentDashboard from "@/dashboards/Agent";
|
|||||||
import PaymentDue from "./(status)/PaymentDue";
|
import PaymentDue from "./(status)/PaymentDue";
|
||||||
import {useRouter} from "next/router";
|
import {useRouter} from "next/router";
|
||||||
import {PayPalScriptProvider} from "@paypal/react-paypal-js";
|
import {PayPalScriptProvider} from "@paypal/react-paypal-js";
|
||||||
|
import {CorporateUser, Type, userTypes} from "@/interfaces/user";
|
||||||
|
import Select from "react-select";
|
||||||
|
import {USER_TYPE_LABELS} from "@/resources/user";
|
||||||
|
|
||||||
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||||
const user = req.session.user;
|
const user = req.session.user;
|
||||||
@@ -61,8 +64,9 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
|||||||
export default function Home({envVariables}: {envVariables: {[key: string]: string}}) {
|
export default function Home({envVariables}: {envVariables: {[key: string]: string}}) {
|
||||||
const [showDiagnostics, setShowDiagnostics] = useState(false);
|
const [showDiagnostics, setShowDiagnostics] = useState(false);
|
||||||
const [showDemographicInput, setShowDemographicInput] = useState(false);
|
const [showDemographicInput, setShowDemographicInput] = useState(false);
|
||||||
|
const [selectedScreen, setSelectedScreen] = useState<Type>("admin");
|
||||||
|
|
||||||
const {user, mutateUser} = useUser({redirectTo: "/login"});
|
const {user, mutateUser} = useUser({redirectTo: "/login"});
|
||||||
const {stats} = useStats(user?.id);
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -176,7 +180,21 @@ export default function Home({envVariables}: {envVariables: {[key: string]: stri
|
|||||||
{user.type === "corporate" && <CorporateDashboard user={user} />}
|
{user.type === "corporate" && <CorporateDashboard user={user} />}
|
||||||
{user.type === "agent" && <AgentDashboard user={user} />}
|
{user.type === "agent" && <AgentDashboard user={user} />}
|
||||||
{user.type === "admin" && <AdminDashboard user={user} />}
|
{user.type === "admin" && <AdminDashboard user={user} />}
|
||||||
{user.type === "developer" && <AdminDashboard user={user} />}
|
{user.type === "developer" && (
|
||||||
|
<>
|
||||||
|
<Select
|
||||||
|
options={userTypes.map((u) => ({value: u, label: USER_TYPE_LABELS[u]}))}
|
||||||
|
value={{value: selectedScreen, label: USER_TYPE_LABELS[selectedScreen]}}
|
||||||
|
onChange={(value) => (value ? setSelectedScreen(value.value) : setSelectedScreen("admin"))}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{selectedScreen === "student" && <StudentDashboard user={user} />}
|
||||||
|
{selectedScreen === "teacher" && <TeacherDashboard user={user} />}
|
||||||
|
{selectedScreen === "corporate" && <CorporateDashboard user={user as unknown as CorporateUser} />}
|
||||||
|
{selectedScreen === "agent" && <AgentDashboard user={user} />}
|
||||||
|
{selectedScreen === "admin" && <AdminDashboard user={user} />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Layout>
|
</Layout>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user