Created a screen for the module exam selection
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
/* eslint-disable @next/next/no-img-element */
|
/* eslint-disable @next/next/no-img-element */
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
return (
|
return (
|
||||||
<div className="navbar bg-base-100">
|
<div className="navbar bg-neutral-100 drop-shadow-md text-black">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<a className="btn btn-ghost normal-case text-xl">IELTS GPT</a>
|
<a className="btn btn-ghost normal-case text-xl">IELTS GPT</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-none gap-2">
|
<div className="flex-none gap-2">
|
||||||
<div className="form-control">
|
<div className="form-control">
|
||||||
<input type="text" placeholder="Search" className="input input-bordered" />
|
<input type="text" placeholder="Search" className="input input-bordered bg-white" />
|
||||||
</div>
|
</div>
|
||||||
<div className="dropdown dropdown-end">
|
<div className="dropdown dropdown-end">
|
||||||
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
|
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {Module} from "@/interfaces";
|
import {Module} from "@/interfaces";
|
||||||
import {UserResults} from "@/interfaces/results";
|
import {UserResults} from "@/interfaces/results";
|
||||||
|
import {SEMI_TRANSPARENT} from "@/resources/colors";
|
||||||
import {moduleLabels} from "@/utils/moduleUtils";
|
import {moduleLabels} from "@/utils/moduleUtils";
|
||||||
import {Chart as ChartJS, RadialLinearScale, ArcElement, Tooltip, Legend} from "chart.js";
|
import {Chart as ChartJS, RadialLinearScale, ArcElement, Tooltip, Legend} from "chart.js";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
@@ -22,7 +23,7 @@ export default function UserResultChart({results, resultKey, label, className =
|
|||||||
{
|
{
|
||||||
label,
|
label,
|
||||||
data: Object.keys(results).map((module) => results[module as Module][resultKey]),
|
data: Object.keys(results).map((module) => results[module as Module][resultKey]),
|
||||||
backgroundColor: ["rgba(255, 99, 132, 0.5)", "rgba(54, 162, 235, 0.5)", "rgba(255, 206, 86, 0.5)", "rgba(75, 192, 192, 0.5)"],
|
backgroundColor: Object.values(SEMI_TRANSPARENT),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
129
src/pages/exam.tsx
Normal file
129
src/pages/exam.tsx
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/* eslint-disable @next/next/no-img-element */
|
||||||
|
import Head from "next/head";
|
||||||
|
import Navbar from "@/components/Navbar";
|
||||||
|
import Icon from "@mdi/react";
|
||||||
|
import {mdiAccountVoice, mdiArrowLeft, mdiArrowRight, mdiBookOpen, mdiHeadphones, mdiPen} from "@mdi/js";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {Module} from "@/interfaces";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import {useRouter} from "next/router";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const [selectedModules, setSelectedModules] = useState<Module[]>([]);
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const toggleModule = (module: Module) => {
|
||||||
|
const modules = selectedModules.filter((x) => x !== module);
|
||||||
|
setSelectedModules((prev) => (prev.includes(module) ? modules : [...modules, module]));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Create Next App</title>
|
||||||
|
<meta name="description" content="Generated by create next app" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
</Head>
|
||||||
|
<main className="w-full h-screen flex flex-col items-center bg-white text-black">
|
||||||
|
<Navbar />
|
||||||
|
<div className="w-full h-full relative">
|
||||||
|
<section className="h-full w-full flex flex-col items-center justify-center">
|
||||||
|
<div className="h-1/2 flex flex-col items-center justify-center gap-4">
|
||||||
|
<div className="w-24 rounded-full">
|
||||||
|
<img
|
||||||
|
src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg"
|
||||||
|
alt="Profile picture"
|
||||||
|
className="rounded-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-4 items-center">
|
||||||
|
<span className="text-xl font-semibold text-success">Professional</span>
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="flex gap-3 items-center">
|
||||||
|
<span>Lvl. 34</span>
|
||||||
|
<progress className="progress progress-success w-64" value="54" max="100" />
|
||||||
|
<span>Lvl. 35</span>
|
||||||
|
</div>
|
||||||
|
<span className="text-xs">5 400 / 10 000</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="h-1/2 flex flex-col">
|
||||||
|
<div className="h-1/2 flex gap-8">
|
||||||
|
<div
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => toggleModule("reading")}
|
||||||
|
className={clsx(
|
||||||
|
"flex flex-col gap-2 items-center justify-center",
|
||||||
|
"border-ielts-reading hover:bg-ielts-reading",
|
||||||
|
"border-2 rounded-xl p-4 h-fit w-48 cursor-pointer",
|
||||||
|
selectedModules.includes("reading") ? "bg-ielts-reading " : "bg-ielts-reading-transparent ",
|
||||||
|
)}>
|
||||||
|
<Icon path={mdiBookOpen} color="white" size={3} />
|
||||||
|
<span>Reading</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => toggleModule("listening")}
|
||||||
|
className={clsx(
|
||||||
|
"flex flex-col gap-2 items-center justify-center",
|
||||||
|
"border-ielts-listening hover:bg-ielts-listening",
|
||||||
|
"border-2 rounded-xl p-4 h-fit w-48 cursor-pointer",
|
||||||
|
selectedModules.includes("listening") ? "bg-ielts-listening " : "bg-ielts-listening-transparent ",
|
||||||
|
)}>
|
||||||
|
<Icon path={mdiHeadphones} color="white" size={3} />
|
||||||
|
<span>Listening</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => toggleModule("speaking")}
|
||||||
|
className={clsx(
|
||||||
|
"flex flex-col gap-2 items-center justify-center",
|
||||||
|
"border-ielts-speaking hover:bg-ielts-speaking",
|
||||||
|
"border-2 rounded-xl p-4 h-fit w-48 cursor-pointer",
|
||||||
|
selectedModules.includes("speaking") ? "bg-ielts-speaking " : "bg-ielts-speaking-transparent ",
|
||||||
|
)}>
|
||||||
|
<Icon path={mdiAccountVoice} color="white" size={3} />
|
||||||
|
<span>Speaking</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => toggleModule("writing")}
|
||||||
|
className={clsx(
|
||||||
|
"flex flex-col gap-2 items-center justify-center",
|
||||||
|
"border-ielts-writing hover:bg-ielts-writing",
|
||||||
|
"border-2 rounded-xl p-4 h-fit w-48 cursor-pointer",
|
||||||
|
selectedModules.includes("writing") ? "bg-ielts-writing " : "bg-ielts-writing-transparent ",
|
||||||
|
)}>
|
||||||
|
<Icon path={mdiPen} color="white" size={3} />
|
||||||
|
<span>Writing</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="w-full flex justify-between">
|
||||||
|
<button
|
||||||
|
onClick={() => router.push("/")}
|
||||||
|
className="btn btn-wide bg-red-500 bg-opacity-50 hover:bg-opacity-100 hover:bg-red-500 border-red-500 border-2 hover:border-red-500 disabled:text-white gap-4 relative text-white">
|
||||||
|
<div className="absolute left-4">
|
||||||
|
<Icon path={mdiArrowLeft} color="white" size={1} />
|
||||||
|
</div>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button className="btn btn-wide bg-blue-500 bg-opacity-50 hover:bg-opacity-100 hover:bg-blue-500 border-blue-500 border-2 hover:border-blue-500 gap-4 relative text-white">
|
||||||
|
Start
|
||||||
|
<div className="absolute right-4">
|
||||||
|
<Icon path={mdiArrowRight} color="white" size={1} />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import JSON_RESULTS from "@/demo/user_results.json";
|
|||||||
import Navbar from "@/components/Navbar";
|
import Navbar from "@/components/Navbar";
|
||||||
import Icon from "@mdi/react";
|
import Icon from "@mdi/react";
|
||||||
import {mdiPlus} from "@mdi/js";
|
import {mdiPlus} from "@mdi/js";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
const inter = Inter({subsets: ["latin"]});
|
const inter = Inter({subsets: ["latin"]});
|
||||||
|
|
||||||
@@ -19,13 +20,15 @@ export default function Home() {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
<main className="w-full h-screen flex flex-col items-center">
|
<main className="w-full h-screen flex flex-col items-center bg-white">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div className="w-full h-full p-4 relative">
|
<div className="w-full h-full p-4 relative">
|
||||||
<button className="btn gap-2 right-4 absolute">
|
<Link href="/exam">
|
||||||
<Icon path={mdiPlus} color="white" size={1} />
|
<button className="btn btn-primary gap-2 right-4 absolute">
|
||||||
New Exam
|
<Icon path={mdiPlus} color="white" size={1} />
|
||||||
</button>
|
New Exam
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
<section className="h-full w-full grid grid-cols-2 place-items-center">
|
<section className="h-full w-full grid grid-cols-2 place-items-center">
|
||||||
<UserResultChart results={JSON_RESULTS} resultKey="score" label="User results" className="w-5/6" />
|
<UserResultChart results={JSON_RESULTS} resultKey="score" label="User results" className="w-5/6" />
|
||||||
<UserResultChart results={JSON_RESULTS} resultKey="total" label="Total exams" className="w-5/6" />
|
<UserResultChart results={JSON_RESULTS} resultKey="total" label="Total exams" className="w-5/6" />
|
||||||
|
|||||||
15
src/resources/colors.ts
Normal file
15
src/resources/colors.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import {Module} from "@/interfaces";
|
||||||
|
|
||||||
|
export const OPAQUE: {[key in Module]: string} = {
|
||||||
|
reading: "#FF6384",
|
||||||
|
listening: "#36A2EB",
|
||||||
|
writing: "#FFCE56",
|
||||||
|
speaking: "#4bc0c0",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SEMI_TRANSPARENT: {[key in Module]: string} = {
|
||||||
|
reading: "rgba(255, 99, 132, 0.5)",
|
||||||
|
listening: "rgba(54, 162, 235, 0.5)",
|
||||||
|
writing: "rgba(255, 206, 86, 0.5)",
|
||||||
|
speaking: "rgba(75, 192, 192, 0.5)",
|
||||||
|
};
|
||||||
@@ -2,7 +2,16 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
content: ["./src/**/*.{html,tsx,ts,js,jsx}"],
|
content: ["./src/**/*.{html,tsx,ts,js,jsx}"],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {
|
||||||
|
colors: {
|
||||||
|
ielts: {
|
||||||
|
reading: {DEFAULT: "#FF6384", transparent: "rgba(255, 99, 132, 0.5)"},
|
||||||
|
listening: {DEFAULT: "#36A2EB", transparent: "rgba(54, 162, 235, 0.5)"},
|
||||||
|
writing: {DEFAULT: "#FFCE56", transparent: "rgba(255, 206, 86, 0.5)"},
|
||||||
|
speaking: {DEFAULT: "#4bc0c0", transparent: "rgba(75, 192, 192, 0.5)"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("daisyui")],
|
plugins: [require("daisyui")],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user