Skip to content

Commit 0dfa0ab

Browse files
Merge pull request #24 from monicasmith463/feature/frontend-exam-view
Feature: frontend Take Exam form
2 parents a25eb83 + 68df355 commit 0dfa0ab

File tree

7 files changed

+359
-3
lines changed

7 files changed

+359
-3
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import TakeExamForm from "@/components/exam/TakeExamForm";
2+
import { Metadata } from "next";
3+
4+
export const metadata: Metadata = {
5+
title: "Next.js TakeExam Page",
6+
description: "This is Next.js TakeExam Page",
7+
};
8+
9+
export default function TakeExam() {
10+
return <TakeExamForm />;
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import ListWithRadio from "../ui/list/ListWithRadio";
2+
3+
export default function QuestionInput() {
4+
return (
5+
<div className="col-span-full">
6+
7+
<ListWithRadio />
8+
</div>)
9+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"use client";
2+
import React from "react";
3+
import Button from "../ui/button/Button";
4+
import Form from "../form/Form";
5+
import ComponentCard from "../common/ComponentCard";
6+
import QuestionInput from "./QuestionInput";
7+
8+
export default function TakeExamForm() {
9+
const handleSubmit = (e: React.FormEvent) => {
10+
e.preventDefault();
11+
console.log("Form submitted:");
12+
};
13+
return (
14+
<ComponentCard title="Exam Form">
15+
<Form onSubmit={handleSubmit}>
16+
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
17+
18+
19+
{Array.from({ length: 5 }).map((_, i) => (
20+
<QuestionInput key={i} />
21+
))}
22+
23+
24+
<div className="col-span-full">
25+
<Button className="w-full" size="sm">
26+
Submit
27+
</Button>
28+
</div>
29+
</div>
30+
</Form>
31+
</ComponentCard>
32+
);
33+
}

frontend/src/components/form/form-elements/DocumentDropZone.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import React, { useState } from "react";
33
import ComponentCard from "../../common/ComponentCard";
44
import { useDropzone } from "react-dropzone";
5-
import Button from "@/components/ui/button/Button";
5+
import SpinnerButton from "@/components/ui/button/SpinnerButton";
66

77
const DropzoneComponent: React.FC = () => {
88
const [files, setFiles] = useState<File[]>([]);
@@ -95,9 +95,9 @@ const DropzoneComponent: React.FC = () => {
9595
)}
9696
</div>
9797
<div className="flex items-center justify-right">
98-
<Button size="md" variant="primary" disabled={files.length === 0} className="flex mt-6 mx-auto">
98+
<SpinnerButton size="md" variant="primary" disabled={files.length === 0} loading={false} className="flex mt-6 mx-auto">
9999
Create Exam!
100-
</Button>
100+
</SpinnerButton>
101101
</div>
102102

103103
</ComponentCard>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React, { ReactNode } from "react";
2+
import Button from "./Button";
3+
import Spinner from "@/components/ui/spinner";
4+
5+
interface SpinnerButtonProps {
6+
variant?: "primary" | "secondary" | "tertiary"; // Button variant
7+
size?: "sm" | "md" | undefined;
8+
children: ReactNode; // Button text or content
9+
startIcon?: ReactNode; // Icon before the text
10+
onClick?: () => void; // Click handler
11+
disabled?: boolean; // Disabled state
12+
className?: string; // Disabled state
13+
loading?: boolean; // Loading state
14+
}
15+
16+
const SpinnerButton: React.FC<SpinnerButtonProps> = ({
17+
children,
18+
startIcon,
19+
onClick,
20+
className = "",
21+
disabled = false,
22+
loading = false,
23+
...props
24+
}) => {
25+
return (
26+
<Button
27+
{...props}
28+
startIcon={loading ? <Spinner /> : startIcon}
29+
disabled={disabled || loading}
30+
onClick={onClick}
31+
className={className}
32+
variant="primary"
33+
34+
35+
>
36+
{children}
37+
</Button>
38+
);
39+
};
40+
41+
export default SpinnerButton;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"use client";
2+
import React, { useState } from "react";
3+
import RadioSm from "../../form/input/RadioSm";
4+
5+
export default function ListWithRadio() {
6+
const [selectedValue, setSelectedValue] = useState<string>("option1");
7+
8+
const handleChange = (value: string) => {
9+
setSelectedValue(value);
10+
console.log("Selected Value:", value);
11+
};
12+
return (
13+
<div className="rounded-lg border border-gray-200 bg-white dark:border-gray-800 dark:bg-white/[0.03] sm:w-fit">
14+
<ul className="flex flex-col">
15+
<li className="border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800">
16+
<RadioSm
17+
id="option1"
18+
name="example"
19+
value="option1"
20+
checked={selectedValue === "option1"}
21+
label="Lorem ipsum dolor sit amet"
22+
onChange={handleChange}
23+
/>
24+
</li>
25+
<li className="border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800">
26+
<RadioSm
27+
id="option2"
28+
name="example"
29+
value="option2"
30+
checked={selectedValue === "option2"}
31+
label="It is a long established fact reader"
32+
onChange={handleChange}
33+
/>
34+
</li>
35+
<li className="border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800">
36+
<RadioSm
37+
id="option3"
38+
name="example"
39+
value="option3"
40+
checked={selectedValue === "option3"}
41+
label="Lorem ipsum dolor sit amet"
42+
onChange={handleChange}
43+
/>
44+
</li>
45+
<li className="border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800">
46+
<RadioSm
47+
id="option4"
48+
name="example"
49+
value="option4"
50+
checked={selectedValue === "option4"}
51+
label="Lorem ipsum dolor sit amet"
52+
onChange={handleChange}
53+
/>
54+
</li>
55+
<li className="border-b border-gray-200 px-3 py-2.5 last:border-b-0 dark:border-gray-800">
56+
<RadioSm
57+
id="option5"
58+
name="example"
59+
value="option5"
60+
checked={selectedValue === "option5"}
61+
label="Lorem ipsum dolor sit amet"
62+
onChange={handleChange}
63+
/>
64+
</li>
65+
</ul>
66+
</div>
67+
);
68+
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import React from "react";
2+
3+
4+
5+
export default function Spinner() {
6+
return (
7+
<div className="flex items-center justify-center gap-4 sm:justify-normal">
8+
<div className="animate-spin">
9+
<svg
10+
width="20"
11+
height="20"
12+
viewBox="0 0 20 20"
13+
fill="none"
14+
xmlns="http://www.w3.org/2000/svg"
15+
>
16+
<g clipPath="url(#clip0_3755_26222)">
17+
<path
18+
opacity="0.33"
19+
fillRule="evenodd"
20+
clipRule="evenodd"
21+
d="M12.6065 0.345176L12.1758 1.95287C11.9416 1.88993 11.7051 1.83929 11.4631 1.79612C11.2211 1.75296 10.9817 1.71873 10.7401 1.6968L10.8919 0.0393588C11.1793 0.065229 11.4686 0.104137 11.7557 0.15535C12.0429 0.206563 12.3278 0.270083 12.6065 0.345176Z"
22+
fill="#465FFF"
23+
/>
24+
<path
25+
opacity="0.38"
26+
fillRule="evenodd"
27+
clipRule="evenodd"
28+
d="M15.0174 1.34668L14.1804 2.78878C13.7667 2.54568 13.3292 2.34069 12.868 2.17378L13.4393 0.608099C13.9919 0.808241 14.5186 1.05878 15.0174 1.34668Z"
29+
fill="#465FFF"
30+
/>
31+
<path
32+
opacity="0.42"
33+
fillRule="evenodd"
34+
clipRule="evenodd"
35+
d="M17.0872 2.94301L15.9045 4.11607C15.5638 3.77174 15.192 3.45993 14.7937 3.17728L15.7559 1.81676C16.233 2.15579 16.6781 2.53145 17.0872 2.94301Z"
36+
fill="#465FFF"
37+
/>
38+
<path
39+
opacity="0.5"
40+
fillRule="evenodd"
41+
clipRule="evenodd"
42+
d="M18.6688 5.01549L17.2256 5.84581C16.9831 5.42586 16.7074 5.02541 16.3972 4.65265L17.6753 3.58549C18.0484 4.03294 18.382 4.51147 18.6688 5.01549Z"
43+
fill="#465FFF"
44+
/>
45+
<path
46+
opacity="0.55"
47+
fillRule="evenodd"
48+
clipRule="evenodd"
49+
d="M19.6684 7.42856L18.0557 7.85621C17.9323 7.38556 17.7642 6.92809 17.5622 6.49423L19.0718 5.79002C19.3166 6.31617 19.5152 6.86372 19.6684 7.42856Z"
50+
fill="#465FFF"
51+
/>
52+
<path
53+
opacity="0.6"
54+
fillRule="evenodd"
55+
clipRule="evenodd"
56+
d="M20.0023 10.0191L18.3356 10.0139C18.3384 9.52342 18.2932 9.04132 18.213 8.56568L19.8548 8.2829C19.9532 8.84644 20.0055 9.43137 20.0023 10.0191Z"
57+
fill="#465FFF"
58+
/>
59+
<path
60+
opacity="0.65"
61+
fillRule="evenodd"
62+
clipRule="evenodd"
63+
d="M19.8449 11.7559C19.7937 12.043 19.7302 12.328 19.6551 12.6066L18.044 12.1711C18.1062 11.941 18.161 11.7053 18.2041 11.4633C18.2473 11.2212 18.2782 10.977 18.2993 10.7396L19.9609 10.892C19.9358 11.1753 19.8968 11.4647 19.8449 11.7559Z"
64+
fill="#465FFF"
65+
/>
66+
<path
67+
opacity="0.7"
68+
fillRule="evenodd"
69+
clipRule="evenodd"
70+
d="M19.3919 13.436C19.191 13.9927 18.9405 14.5194 18.6526 15.0182L17.2105 14.1812C17.4495 13.7667 17.6593 13.3259 17.8262 12.8647L19.3919 13.436Z"
71+
fill="#465FFF"
72+
/>
73+
<path
74+
opacity="0.75"
75+
fillRule="evenodd"
76+
clipRule="evenodd"
77+
d="M18.1846 15.7511C17.8448 16.2323 17.4691 16.6774 17.0583 17.0824L15.8845 15.9038C16.2248 15.5624 16.5407 15.1913 16.8192 14.7923L18.1846 15.7511Z"
78+
fill="#465FFF"
79+
/>
80+
<path
81+
opacity="0.8"
82+
fillRule="evenodd"
83+
clipRule="evenodd"
84+
d="M16.4122 17.67C15.9688 18.0438 15.4903 18.3774 14.9855 18.6683L14.1552 17.2251C14.5752 16.9826 14.9723 16.7021 15.345 16.3919L16.4122 17.67Z"
85+
fill="#465FFF"
86+
/>
87+
<path
88+
opacity="0.95"
89+
fillRule="evenodd"
90+
clipRule="evenodd"
91+
d="M14.2118 19.0721C13.6856 19.3168 13.1381 19.5154 12.574 19.6645L12.1415 18.0552C12.6129 17.9277 13.0696 17.7637 13.5083 17.5584L14.2118 19.0721Z"
92+
fill="#465FFF"
93+
/>
94+
<path
95+
fillRule="evenodd"
96+
clipRule="evenodd"
97+
d="M11.7166 19.8506C11.1483 19.9524 10.5682 20.0013 9.97971 20.0021L9.98494 18.3355C10.4761 18.3342 10.9575 18.2931 11.429 18.2121L11.7166 19.8506Z"
98+
fill="#465FFF"
99+
/>
100+
<path
101+
opacity="0.05"
102+
fillRule="evenodd"
103+
clipRule="evenodd"
104+
d="M9.10628 19.9606C8.81886 19.9347 8.52953 19.8958 8.2424 19.8446C7.95526 19.7934 7.67032 19.7298 7.39168 19.6547L7.82306 18.0429C8.05731 18.1059 8.29303 18.1606 8.53504 18.2038C8.77706 18.247 9.01717 18.2771 9.25874 18.299L9.10628 19.9606Z"
105+
fill="#465FFF"
106+
/>
107+
<path
108+
opacity="0.07"
109+
fillRule="evenodd"
110+
clipRule="evenodd"
111+
d="M7.13218 17.8261L6.56089 19.3917C6.00901 19.1875 5.48159 18.9411 4.98345 18.6491L5.81978 17.2111C6.23425 17.4501 6.67172 17.6551 7.13218 17.8261Z"
112+
fill="#465FFF"
113+
/>
114+
<path
115+
opacity="0.09"
116+
fillRule="evenodd"
117+
clipRule="evenodd"
118+
d="M5.20654 16.8185L4.24436 18.179C3.76658 17.8441 3.32146 17.4684 2.91237 17.0569L4.09579 15.8797C4.43645 16.224 4.80831 16.5358 5.20654 16.8185Z"
119+
fill="#465FFF"
120+
/>
121+
<path
122+
opacity="0.11"
123+
fillRule="evenodd"
124+
clipRule="evenodd"
125+
d="M3.60309 15.3433L2.32501 16.4105C1.95195 15.963 1.61829 15.4845 1.3315 14.9805L2.77472 14.1501C3.01725 14.5701 3.29289 14.9705 3.60309 15.3433Z"
126+
fill="#465FFF"
127+
/>
128+
<path
129+
opacity="0.13"
130+
fillRule="evenodd"
131+
clipRule="evenodd"
132+
d="M2.43882 13.5057L0.929947 14.2058C0.684465 13.6837 0.485856 13.1362 0.333388 12.5672L1.94603 12.1396C2.06948 12.6103 2.2376 13.0677 2.43882 13.5057Z"
133+
fill="#465FFF"
134+
/>
135+
<path
136+
opacity="0.15"
137+
fillRule="evenodd"
138+
clipRule="evenodd"
139+
d="M1.78956 11.4303L0.147002 11.7172C0.0493218 11.1495 -0.00368106 10.5687 0.000299417 9.97688L1.66694 9.98211C1.66411 10.4726 1.7086 10.9588 1.78956 11.4303Z"
140+
fill="#465FFF"
141+
/>
142+
<path
143+
opacity="0.17"
144+
fillRule="evenodd"
145+
clipRule="evenodd"
146+
d="M1.79646 8.53667C1.75329 8.77868 1.72316 9.01879 1.70197 9.25626L0.0396938 9.10791C0.0655641 8.82049 0.104472 8.53116 0.155685 8.24402C0.206899 7.95689 0.271149 7.66784 0.345511 7.3933L1.95731 7.82469C1.89509 8.05484 1.83962 8.29466 1.79646 8.53667Z"
147+
fill="#465FFF"
148+
/>
149+
<path
150+
opacity="0.19"
151+
fillRule="evenodd"
152+
clipRule="evenodd"
153+
d="M2.78818 5.8148C2.54846 6.23338 2.33936 6.67011 2.17245 7.1313L0.606769 6.56001C0.806911 6.0074 1.05818 5.47661 1.34535 4.98185L2.78818 5.8148Z"
154+
fill="#465FFF"
155+
/>
156+
<path
157+
opacity="0.21"
158+
fillRule="evenodd"
159+
clipRule="evenodd"
160+
d="M4.1165 4.09609C3.777 4.43338 3.46109 4.80451 3.18254 5.20347L1.81718 4.24467C2.15622 3.76762 2.53188 3.3225 2.94344 2.91341L4.1165 4.09609Z"
161+
fill="#465FFF"
162+
/>
163+
<path
164+
opacity="0.25"
165+
fillRule="evenodd"
166+
clipRule="evenodd"
167+
d="M5.84508 2.77086C5.42513 3.01339 5.02805 3.29386 4.65529 3.60406L3.58813 2.32599C4.03148 1.9522 4.51 1.61853 5.01476 1.32764L5.84508 2.77086Z"
168+
fill="#465FFF"
169+
/>
170+
<path
171+
opacity="0.28"
172+
fillRule="evenodd"
173+
clipRule="evenodd"
174+
d="M7.86269 1.94102C7.39131 2.06856 6.93458 2.23258 6.49588 2.4379L5.79167 0.9283C6.31782 0.683551 6.86537 0.484941 7.43021 0.331741L7.86269 1.94102Z"
175+
fill="#465FFF"
176+
/>
177+
<path
178+
opacity="0.3"
179+
fillRule="evenodd"
180+
clipRule="evenodd"
181+
d="M10.0152 1.66437C9.52478 1.66154 9.04342 1.70265 8.57114 1.78772L8.28427 0.145157C8.8519 0.0474769 9.43273 -0.00552584 10.0205 -0.00227699L10.0152 1.66437Z"
182+
fill="#465FFF"
183+
/>
184+
</g>
185+
<defs>
186+
<clipPath id="clip0_3755_26222">
187+
<rect width="20" height="20" fill="white" />
188+
</clipPath>
189+
</defs>
190+
</svg>
191+
</div>
192+
</div>
193+
);
194+
}

0 commit comments

Comments
 (0)