From 7ef95a323e00b21ae7b1377f6cba5fde5ddab6c9 Mon Sep 17 00:00:00 2001 From: Prakhar Date: Tue, 15 Aug 2023 22:45:32 +0530 Subject: [PATCH 1/8] Storing user data from the forms --- package-lock.json | 9 + package.json | 1 + .../Options/StudentDetailsOptions.tsx | 12 +- src/components/Options/TestDetailsOptions.tsx | 9 +- src/components/Options/TimelineOptions.tsx | 10 +- src/components/Stepper.tsx | 53 ++--- src/components/Steps/StudentDetails.tsx | 197 ++++++++++-------- src/components/Steps/TestDetails.tsx | 92 +++++--- src/components/Steps/Timeline.tsx | 64 ++++-- src/components/displayTable/DataDisplay.tsx | 35 ++++ src/components/displayTable/Row.tsx | 5 + src/pages/SessionCreator.tsx | 41 +++- src/pages/SessionInfo.tsx | 26 --- src/pages/index.tsx | 160 +++++++++++++- src/types/types.ts | 9 + 15 files changed, 499 insertions(+), 224 deletions(-) create mode 100644 src/components/displayTable/DataDisplay.tsx create mode 100644 src/components/displayTable/Row.tsx delete mode 100644 src/pages/SessionInfo.tsx create mode 100644 src/types/types.ts diff --git a/package-lock.json b/package-lock.json index 116303c..8ab3f15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "cross-env": "^7.0.3", "eslint": "8.44.0", "eslint-config-next": "13.4.9", + "feather-icons-react": "^0.6.2", "next": "13.4.9", "pre-commit": "^1.2.2", "react": "18.2.0", @@ -2175,6 +2176,14 @@ "reusify": "^1.0.4" } }, + "node_modules/feather-icons-react": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/feather-icons-react/-/feather-icons-react-0.6.2.tgz", + "integrity": "sha512-G677Y5nc3HzP1f5NNb5LJuZwKrI58BK4+/9O8Bl4naF9JixC+YL4trVom1F2ajnilq/EbU8JETPTNqvCzwH1qA==", + "peerDependencies": { + "react": ">= 16.8.4" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", diff --git a/package.json b/package.json index e212fda..e14773a 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "cross-env": "^7.0.3", "eslint": "8.44.0", "eslint-config-next": "13.4.9", + "feather-icons-react": "^0.6.2", "next": "13.4.9", "pre-commit": "^1.2.2", "react": "18.2.0", diff --git a/src/components/Options/StudentDetailsOptions.tsx b/src/components/Options/StudentDetailsOptions.tsx index 894b518..572c069 100644 --- a/src/components/Options/StudentDetailsOptions.tsx +++ b/src/components/Options/StudentDetailsOptions.tsx @@ -1,7 +1,7 @@ -export type OptionType = { - value: string; +export interface OptionType { + value: string | boolean; label: string; -}; +} const ProgramOptions: OptionType[] = [ { value: "Haryana Students", label: "Haryana Students" }, @@ -174,10 +174,10 @@ const TestTakersOptions = [ ]; export { - ProgramOptions, - GradeOptions, + BatchOptions, CourseOptions, + GradeOptions, + ProgramOptions, StreamOptions, TestTakersOptions, - BatchOptions, }; diff --git a/src/components/Options/TestDetailsOptions.tsx b/src/components/Options/TestDetailsOptions.tsx index 5c2fbbb..7d4ff1c 100644 --- a/src/components/Options/TestDetailsOptions.tsx +++ b/src/components/Options/TestDetailsOptions.tsx @@ -1,7 +1,4 @@ -export type OptionType = { - value: string; - label: string; -}; +import { OptionType } from "./StudentDetailsOptions"; const TestTypeOptions: OptionType[] = [ { value: "assessment", label: "Assessment" }, @@ -44,9 +41,9 @@ const OptionalLimitOptions: OptionType[] = [ export { MarkingSchemeOptions, + OptionalLimitOptions, TestFormatOptions, - TestPurposeOptions, TestPlatformOptions, + TestPurposeOptions, TestTypeOptions, - OptionalLimitOptions, }; diff --git a/src/components/Options/TimelineOptions.tsx b/src/components/Options/TimelineOptions.tsx index 0afa374..220a135 100644 --- a/src/components/Options/TimelineOptions.tsx +++ b/src/components/Options/TimelineOptions.tsx @@ -1,16 +1,18 @@ -const IsEnabledOptions = [ +import { OptionType } from "./StudentDetailsOptions"; + +const IsEnabledOptions: OptionType[] = [ { value: true, label: "ON" }, { value: false, label: "OFF" }, ]; -const HasSyncedOptions = [ +const HasSyncedOptions: OptionType[] = [ { value: true, label: "TRUE" }, { value: false, label: "FALSE" }, ]; -const SessionTypeOptions = [ +const SessionTypeOptions: OptionType[] = [ { value: "infinite", label: "Infinite" }, { value: "standard", label: "Standard" }, ]; -export { IsEnabledOptions, HasSyncedOptions, SessionTypeOptions }; +export { HasSyncedOptions, IsEnabledOptions, SessionTypeOptions }; diff --git a/src/components/Stepper.tsx b/src/components/Stepper.tsx index eb6d2dd..0b8f535 100644 --- a/src/components/Stepper.tsx +++ b/src/components/Stepper.tsx @@ -1,40 +1,33 @@ -// Stepper.js -import { Step } from "@/pages/SessionCreator"; -import React from "react"; - -//Navigates throught different sub-pages by passing the current step and the active step and renders the components based on the sub-page user is presented at export default function Stepper({ steps, activeStep, }: { - steps: Step[]; + steps: string[]; activeStep: string; }) { return ( - <> -
    - {steps.map((step, index) => ( -
  1. + {steps.map((step, index) => ( +
  2. + - - {index + 1} - - -

    - {step} -

    -
    -
  3. - ))} -
- + {index + 1} + + +

+ {step} +

+
+ + ))} + ); } diff --git a/src/components/Steps/StudentDetails.tsx b/src/components/Steps/StudentDetails.tsx index 69a00ab..eb3d75d 100644 --- a/src/components/Steps/StudentDetails.tsx +++ b/src/components/Steps/StudentDetails.tsx @@ -1,107 +1,124 @@ -import React, { Dispatch, SetStateAction, useState } from "react"; +import { Step } from "@/pages/SessionCreator"; +import { ActiveFormProps } from "@/types/types"; +import { useState, type MouseEvent } from "react"; import Select from "react-select"; import styles from "../../styles/Home.module.css"; import { + BatchOptions, CourseOptions, GradeOptions, + OptionType, ProgramOptions, StreamOptions, - BatchOptions, } from "../Options/StudentDetailsOptions"; -import { OptionType } from "../Options/StudentDetailsOptions"; -const Steps = { - StudentDetails: "StudentDetails", - TestDetails: "TestDetails", -}; -// Renders the sub-page containing student details export default function StudentDetails({ setActiveStep, -}: { - setActiveStep: Dispatch>; -}) { - const [selectedProgram, setSelectedProgram] = useState( - ProgramOptions[0] - ); - const [selectedBatch, setSelectedBatch] = useState( - BatchOptions[0] - ); + setData, +}: ActiveFormProps) { + const [studentData, setStudentData] = useState<{ + [key: string]: OptionType | null; + }>({ + program: null, + batch: null, + grade: null, + course: null, + stream: null, + }); - const [selectedGrade, setSelectedGrade] = useState( - GradeOptions[0] - ); - const [selectedCourse, setSelectedCourse] = useState( - CourseOptions[0] - ); - const [selectedStream, setSelectedStream] = useState( - StreamOptions[0] - ); + const handleClick = (e: MouseEvent) => { + e.preventDefault(); + + setData((prevData) => ({ ...prevData, studentData })); + + setActiveStep(Step.TEST_DETAILS); + }; return ( - <> -
-
- {/* Select inputs */} - setSelectedBatch(selectedOption)} - instanceId="batchSelect" - isSearchable - placeholder="Batch" - /> - setSelectedCourse(selectedOption)} - instanceId="courseSelect" - isSearchable - placeholder="Course" - /> - +
+ + + setStudentData({ + ...studentData, + batch: selectedOption, + }) + } + instanceId="batchSelect" + isSearchable + placeholder="Batch" + /> + + setStudentData({ + ...studentData, + course: selectedOption, + }) + } + instanceId="courseSelect" + isSearchable + placeholder="Course" + /> + - - -
- + + +
); } diff --git a/src/components/Steps/TestDetails.tsx b/src/components/Steps/TestDetails.tsx index 18a4168..593d18d 100644 --- a/src/components/Steps/TestDetails.tsx +++ b/src/components/Steps/TestDetails.tsx @@ -1,25 +1,39 @@ -import React, { useState } from "react"; +import { MouseEvent, useState } from "react"; import styles from "../../styles/Home.module.css"; +import { Step } from "@/pages/SessionCreator"; +import { ActiveFormProps } from "@/types/types"; import Select from "react-select"; +import { OptionType } from "../Options/StudentDetailsOptions"; import { MarkingSchemeOptions, + OptionalLimitOptions, TestFormatOptions, TestPlatformOptions, TestPurposeOptions, TestTypeOptions, - OptionalLimitOptions, } from "../Options/TestDetailsOptions"; // Renders sub-page containing test details -export default function TestDetails({ setActiveStep }) { - const [selectedTestType, setSelectedTestType] = useState(null); - const [selectedTestFormat, setSelectedTestFormat] = useState(null); - const [selectedTestPurpose, setSelectedTestPurpose] = useState(null); - const [selectedTestPlatform, setSelectedTestPlatform] = useState(null); - const [selectedMarkingScheme, setSelectedMarkingScheme] = useState(null); - const [selectedOptionalLimit, setSelectedOptionalLimit] = useState(null); +export function TestDetails({ setActiveStep, setData }: ActiveFormProps) { + const [testData, setTestData] = useState<{ + [key: string]: OptionType | null; + }>({ + testType: null, + testFormat: null, + testPurpose: null, + testPlatform: null, + markingScheme: null, + optionalLimit: null, + }); + + const handleClick = (e: MouseEvent) => { + e.preventDefault(); + setData((prevData: Object) => ({ ...prevData, testData })); + setActiveStep(Step.TIMELINE); + }; + return ( <>
@@ -28,8 +42,13 @@ export default function TestDetails({ setActiveStep }) { setSelectedTestFormat(selectedOption)} + value={testData.testFormat} + onChange={(selectedOption) => + setTestData({ + ...testData, + testFormat: selectedOption, + }) + } instanceId="test_formatSelect" isSearchable placeholder="Test Format" @@ -46,9 +70,12 @@ export default function TestDetails({ setActiveStep }) { - setSelectedTestPlatform(selectedOption) + setTestData({ + ...testData, + testPlatform: selectedOption, + }) } instanceId="test_platformSelect" isSearchable @@ -68,25 +98,31 @@ export default function TestDetails({ setActiveStep }) { - setSelectedMarkingScheme(selectedOption) + setTestData({ + ...testData, + optionalLimit: selectedOption, + }) } - instanceId="marking_schemeSelect" isSearchable - placeholder="Marking Scheme" + instanceId="Optional_limitSelect" + placeholder="Optional Limit" /> { - setActiveStep("StudentDetails"); + setActiveStep(Step.STUDENT_DETAILS); }} > Back diff --git a/src/components/Steps/Timeline.tsx b/src/components/Steps/Timeline.tsx index 23e939d..c19b7a1 100644 --- a/src/components/Steps/Timeline.tsx +++ b/src/components/Steps/Timeline.tsx @@ -1,21 +1,34 @@ -import { useRouter } from "next/router"; -import React, { useState } from "react"; +import { MouseEvent, useState } from "react"; import styles from "../../styles/Home.module.css"; +import { Step } from "@/pages/SessionCreator"; +import { ActiveFormProps } from "@/types/types"; import Select from "react-select"; +import { OptionType } from "../Options/StudentDetailsOptions"; import { HasSyncedOptions, - SessionTypeOptions, IsEnabledOptions, + SessionTypeOptions, } from "../Options/TimelineOptions"; -//Renders the sub-page containing details of Session Timeline -export default function Timeline({ setActiveStep }) { - const router = useRouter(); - const [selectedSynced, setSelectedSynced] = useState(null); - const [selectedIsEnabled, setSelectedIsEnabled] = useState(null); - const [selectedSessionType, setSelectedSessionType] = useState(null); - useState(null); +export default function Timeline({ + setActiveStep, + setData, + createSession, +}: ActiveFormProps) { + const [timelineData, setTimelineData] = useState<{ + [key: string]: OptionType | null; + }>({ + isEnabled: null, + sessionType: null, + synced: null, + }); + + const handleClick = (e: MouseEvent) => { + e.preventDefault(); + setData((prevData: Object) => ({ ...prevData, timelineData })); + createSession!(); + }; return ( <>
@@ -54,8 +67,13 @@ export default function Timeline({ setActiveStep }) { - setSelectedSessionType(selectedOption) + setTimelineData({ + ...timelineData, + sessionType: selectedOption, + }) } instanceId="session_typeSelect" isSearchable @@ -74,8 +95,13 @@ export default function Timeline({ setActiveStep }) { -
- - ); -} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index a2c24d0..9f98c1f 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,9 +1,145 @@ +import Button from "@/components/Buttons/Button"; +import DataDisplay from "@/components/displayTable/DataDisplay"; +// import { Inter } from "next/font/google"; import Head from "next/head"; -import { Inter } from "next/font/google"; -import SessionInfo from "./SessionInfo"; -const inter = Inter({ subsets: ["latin"] }); +import { useRouter } from "next/router"; +// const inter = Inter({ subsets: ["latin"] }); + +// TODO: Fetch data from the server using axios +const data = [ + { + studentData: { + program: { + value: "Himachal Students", + label: "Himachal Students", + }, + batch: { + value: "DL-11-Alpha-eng-23", + label: "DL-11-Alpha-eng-23", + }, + grade: { + value: "10", + label: "10", + }, + course: { + value: "Alpha", + label: "Alpha", + }, + stream: { + value: "Medical", + label: "Medical", + }, + }, + testData: { + testType: { + value: "homework", + label: "Homework", + }, + testFormat: { + value: "major_test", + label: "Major Test", + }, + testPurpose: { + value: "weekly_test", + label: "Weekly Test", + }, + testPlatform: { + value: "Quiz", + label: "Quiz", + }, + markingScheme: { + value: "neet", + label: "NEET", + }, + optionalLimit: { + value: "4,-1", + label: "4 , -1", + }, + }, + timelineData: { + isEnabled: { + value: true, + label: "ON", + }, + sessionType: { + value: "infinite", + label: "Infinite", + }, + synced: { + value: false, + label: "FALSE", + }, + }, + }, + { + studentData: { + program: { + value: "Himachal Students", + label: "Himachal Students", + }, + batch: { + value: "DL-11-Alpha-eng-23", + label: "DL-11-Alpha-eng-23", + }, + grade: { + value: "10", + label: "10", + }, + course: { + value: "Alpha", + label: "Alpha", + }, + stream: { + value: "Medical", + label: "Medical", + }, + }, + testData: { + testType: { + value: "homework", + label: "Homework", + }, + testFormat: { + value: "major_test", + label: "Major Test", + }, + testPurpose: { + value: "weekly_test", + label: "Weekly Test", + }, + testPlatform: { + value: "Quiz", + label: "Quiz", + }, + markingScheme: { + value: "neet", + label: "NEET", + }, + optionalLimit: { + value: "4,-1", + label: "4 , -1", + }, + }, + timelineData: { + isEnabled: { + value: true, + label: "ON", + }, + sessionType: { + value: "infinite", + label: "Infinite", + }, + synced: { + value: false, + label: "FALSE", + }, + }, + }, +]; export default function Home() { + const router = useRouter(); + return ( <> @@ -11,7 +147,23 @@ export default function Home() { - + + + + ); } diff --git a/src/types/types.ts b/src/types/types.ts new file mode 100644 index 0000000..fac74f9 --- /dev/null +++ b/src/types/types.ts @@ -0,0 +1,9 @@ +import { Dispatch, SetStateAction } from "react"; + +interface ActiveFormProps { + setActiveStep: Dispatch>; + setData: Dispatch>; + createSession?: () => void; +} + +export type { ActiveFormProps }; From d6c08b6d5e6c67385aeb5f8f53aef29b5dc5c98a Mon Sep 17 00:00:00 2001 From: Prakhar Date: Wed, 16 Aug 2023 06:02:27 +0530 Subject: [PATCH 2/8] Collapsable table representation --- package-lock.json | 9 ++++ package.json | 1 + src/components/displayTable/DataDisplay.tsx | 16 ++----- src/components/displayTable/Row.tsx | 51 ++++++++++++++++++++- src/types/types.ts | 19 +++++++- 5 files changed, 82 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ab3f15..8c5717c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "quizcreator", "version": "0.1.0", "dependencies": { + "@heroicons/react": "^2.0.18", "@types/react-select": "^5.0.1", "cross-env": "^7.0.3", "eslint": "8.44.0", @@ -356,6 +357,14 @@ "@floating-ui/core": "^1.3.1" } }, + "node_modules/@heroicons/react": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz", + "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==", + "peerDependencies": { + "react": ">= 16" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", diff --git a/package.json b/package.json index e14773a..cebf2b6 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "format": "npx prettier --write ." }, "dependencies": { + "@heroicons/react": "^2.0.18", "@types/react-select": "^5.0.1", "cross-env": "^7.0.3", "eslint": "8.44.0", diff --git a/src/components/displayTable/DataDisplay.tsx b/src/components/displayTable/DataDisplay.tsx index 4c4a384..dcb64a5 100644 --- a/src/components/displayTable/DataDisplay.tsx +++ b/src/components/displayTable/DataDisplay.tsx @@ -1,13 +1,7 @@ -import { useState } from "react"; +import { RowType } from "@/types/types"; import TableRow from "./Row"; -const DataDisplay = ({ data }: { data: Object[] }) => { - const [isExpand, setIsExpand] = useState(false); - - const handleRowToggle = () => { - setIsExpand(!isExpand); - }; - console.log(data); +const DataDisplay = ({ data }: { data: RowType[] }) => { return ( @@ -17,15 +11,15 @@ const DataDisplay = ({ data }: { data: Object[] }) => { - + - {data.map((row: object, i: number) => ( - + {data.map((row, i) => ( + ))}
Test Name Start Date End Date#Test TakerTest Taker Report Link Test Link Actions
diff --git a/src/components/displayTable/Row.tsx b/src/components/displayTable/Row.tsx index f4c4d44..e36e55f 100644 --- a/src/components/displayTable/Row.tsx +++ b/src/components/displayTable/Row.tsx @@ -1,5 +1,52 @@ -const TableRow = ({ row }: { row: Object }) => { - return
; +import { RowType } from "@/types/types"; +import { useState } from "react"; + +const TableRow = ({ row, index }: { row: RowType; index: number }) => { + const [isExpand, setIsExpand] = useState(false); + const { + studentData: { batch }, + testData: { testName, testLink, testTaker }, + timelineData: { reportLink, startDate, endDate }, + } = row!; + + return ( + <> + setIsExpand(!isExpand)}> + {index} + + {typeof batch === "object" && batch!.value} + + + {typeof testName === "string" && testName} + + + {typeof startDate === "string" && startDate} + + {typeof endDate === "string" && endDate} + + {typeof testTaker === "string" && testTaker} + + + {typeof reportLink === "string" && reportLink} + + + {typeof testLink === "string" && testLink} + + +
A
+
B
+
C
+ + + + {/* Collabsable Container */} + {isExpand && ( + +
Helllo world
+ + )} + + ); }; export default TableRow; diff --git a/src/types/types.ts b/src/types/types.ts index fac74f9..3174e05 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -1,9 +1,26 @@ import { Dispatch, SetStateAction } from "react"; +interface OptionType { + value: string | boolean; + label: string; +} + interface ActiveFormProps { setActiveStep: Dispatch>; setData: Dispatch>; createSession?: () => void; } -export type { ActiveFormProps }; +interface RowType { + studentData: { + [key: string]: OptionType | string | number | boolean | null; + }; + testData: { + [key: string]: OptionType | string | number | boolean | null; + }; + timelineData: { + [key: string]: OptionType | string | number | boolean | null; + }; +} + +export type { ActiveFormProps, OptionType, RowType }; From c161e4e377bb044d493266077d4400775eb22b97 Mon Sep 17 00:00:00 2001 From: Prakhar Date: Fri, 18 Aug 2023 13:25:08 +0530 Subject: [PATCH 3/8] added icons --- src/components/displayTable/Row.tsx | 113 +++++++++++++++++------ src/pages/index.tsx | 133 +--------------------------- src/utils/data.ts | 74 ++++++++++++++++ 3 files changed, 162 insertions(+), 158 deletions(-) create mode 100644 src/utils/data.ts diff --git a/src/components/displayTable/Row.tsx b/src/components/displayTable/Row.tsx index e36e55f..2bdafbd 100644 --- a/src/components/displayTable/Row.tsx +++ b/src/components/displayTable/Row.tsx @@ -11,38 +11,97 @@ const TableRow = ({ row, index }: { row: RowType; index: number }) => { return ( <> - setIsExpand(!isExpand)}> - {index} - - {typeof batch === "object" && batch!.value} - - - {typeof testName === "string" && testName} - - - {typeof startDate === "string" && startDate} - - {typeof endDate === "string" && endDate} - - {typeof testTaker === "string" && testTaker} - - - {typeof reportLink === "string" && reportLink} - - - {typeof testLink === "string" && testLink} - - -
A
-
B
-
C
+ setIsExpand(!isExpand)}> + {index} + {typeof batch === "object" && batch!.value} + {typeof testName === "string" && testName} + {typeof startDate === "string" && startDate} + {typeof endDate === "string" && endDate} + {typeof testTaker === "string" && testTaker} + {typeof reportLink === "string" && reportLink} + {typeof testLink === "string" && testLink} + +
+ + + +
+
+ + + +
+
+ + + +
- {/* Collabsable Container */} {isExpand && ( -
Helllo world
+ +
+ {/* The collapsible content goes here */} +
+
Test_type
+
test_format
+
test_purpose
+
+ +
+
Test Takers Count
+
optional_limits
+
is_enabled
+
+ +
+
date_created
+
start_time
+
end_time
+
+ +
+
infinite sessions
+
has_synced
+
repeat_schedule
+
+
+ )} diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9f98c1f..02aa8c1 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,141 +1,12 @@ import Button from "@/components/Buttons/Button"; import DataDisplay from "@/components/displayTable/DataDisplay"; +import { data } from "@/utils/data"; // import { Inter } from "next/font/google"; import Head from "next/head"; import { useRouter } from "next/router"; // const inter = Inter({ subsets: ["latin"] }); -// TODO: Fetch data from the server using axios -const data = [ - { - studentData: { - program: { - value: "Himachal Students", - label: "Himachal Students", - }, - batch: { - value: "DL-11-Alpha-eng-23", - label: "DL-11-Alpha-eng-23", - }, - grade: { - value: "10", - label: "10", - }, - course: { - value: "Alpha", - label: "Alpha", - }, - stream: { - value: "Medical", - label: "Medical", - }, - }, - testData: { - testType: { - value: "homework", - label: "Homework", - }, - testFormat: { - value: "major_test", - label: "Major Test", - }, - testPurpose: { - value: "weekly_test", - label: "Weekly Test", - }, - testPlatform: { - value: "Quiz", - label: "Quiz", - }, - markingScheme: { - value: "neet", - label: "NEET", - }, - optionalLimit: { - value: "4,-1", - label: "4 , -1", - }, - }, - timelineData: { - isEnabled: { - value: true, - label: "ON", - }, - sessionType: { - value: "infinite", - label: "Infinite", - }, - synced: { - value: false, - label: "FALSE", - }, - }, - }, - { - studentData: { - program: { - value: "Himachal Students", - label: "Himachal Students", - }, - batch: { - value: "DL-11-Alpha-eng-23", - label: "DL-11-Alpha-eng-23", - }, - grade: { - value: "10", - label: "10", - }, - course: { - value: "Alpha", - label: "Alpha", - }, - stream: { - value: "Medical", - label: "Medical", - }, - }, - testData: { - testType: { - value: "homework", - label: "Homework", - }, - testFormat: { - value: "major_test", - label: "Major Test", - }, - testPurpose: { - value: "weekly_test", - label: "Weekly Test", - }, - testPlatform: { - value: "Quiz", - label: "Quiz", - }, - markingScheme: { - value: "neet", - label: "NEET", - }, - optionalLimit: { - value: "4,-1", - label: "4 , -1", - }, - }, - timelineData: { - isEnabled: { - value: true, - label: "ON", - }, - sessionType: { - value: "infinite", - label: "Infinite", - }, - synced: { - value: false, - label: "FALSE", - }, - }, - }, -]; +// TODO: Will Fetch data from the server using axios export default function Home() { const router = useRouter(); diff --git a/src/utils/data.ts b/src/utils/data.ts new file mode 100644 index 0000000..72d49e7 --- /dev/null +++ b/src/utils/data.ts @@ -0,0 +1,74 @@ +import { RowType } from "@/types/types"; + +export const data: RowType[] = [ + { + studentData: { + program: { + value: "Himachal Students", + label: "Himachal Students", + }, + batch: { + value: "DL-11-Alpha-eng-23", + label: "DL-11-Alpha-eng-23", + }, + grade: { + value: "10", + label: "10", + }, + course: { + value: "Alpha", + label: "Alpha", + }, + stream: { + value: "Medical", + label: "Medical", + }, + }, + testData: { + testName: "Test_name 1515", + testLink: "Test Link", + testTaker: "test_abc", + testType: { + value: "homework", + label: "Homework", + }, + testFormat: { + value: "major_test", + label: "Major Test", + }, + testPurpose: { + value: "weekly_test", + label: "Weekly Test", + }, + testPlatform: { + value: "Quiz", + label: "Quiz", + }, + markingScheme: { + value: "neet", + label: "NEET", + }, + optionalLimit: { + value: "4,-1", + label: "4 , -1", + }, + }, + timelineData: { + startDate: "test_date s", + endDate: "test_date e", + reportLink: "report link", + isEnabled: { + value: true, + label: "ON", + }, + sessionType: { + value: "infinite", + label: "Infinite", + }, + synced: { + value: false, + label: "FALSE", + }, + }, + }, +]; From c99b0a1d51586d7822d0bec7b7db2a4c3045b568 Mon Sep 17 00:00:00 2001 From: Prakhar Date: Mon, 21 Aug 2023 09:19:25 +0530 Subject: [PATCH 4/8] Refactored code using reactform --- package-lock.json | 28 +++ package.json | 3 +- src/components/Steps/Form/SelectedField.tsx | 39 ++++ src/components/Steps/StudentDetails.tsx | 111 +++-------- src/components/Steps/TestDetails.tsx | 146 ++++++-------- src/components/Steps/Timeline.tsx | 199 +++++++++----------- src/components/displayTable/DataDisplay.tsx | 44 +++-- src/components/displayTable/Row.tsx | 126 ++++--------- src/pages/SessionCreator.tsx | 33 +++- src/pages/index.tsx | 10 +- src/types/FormTypes.ts | 40 ++++ src/types/types.ts | 15 +- src/utils/data.ts | 94 +++------ 13 files changed, 408 insertions(+), 480 deletions(-) create mode 100644 src/components/Steps/Form/SelectedField.tsx create mode 100644 src/types/FormTypes.ts diff --git a/package-lock.json b/package-lock.json index 8c5717c..0a75b85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,8 @@ "pre-commit": "^1.2.2", "react": "18.2.0", "react-dom": "18.2.0", + "react-feather": "^2.0.10", + "react-hook-form": "^7.45.4", "react-select": "^5.7.4", "typescript": "^5.1.6" }, @@ -3853,6 +3855,32 @@ "react": "^18.2.0" } }, + "node_modules/react-feather": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz", + "integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">=16.8.6" + } + }, + "node_modules/react-hook-form": { + "version": "7.45.4", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.45.4.tgz", + "integrity": "sha512-HGDV1JOOBPZj10LB3+OZgfDBTn+IeEsNOKiq/cxbQAIbKaiJUe/KV8DBUzsx0Gx/7IG/orWqRRm736JwOfUSWQ==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index cebf2b6..e17b9a3 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,12 @@ "cross-env": "^7.0.3", "eslint": "8.44.0", "eslint-config-next": "13.4.9", - "feather-icons-react": "^0.6.2", "next": "13.4.9", "pre-commit": "^1.2.2", "react": "18.2.0", "react-dom": "18.2.0", + "react-feather": "^2.0.10", + "react-hook-form": "^7.45.4", "react-select": "^5.7.4", "typescript": "^5.1.6" }, diff --git a/src/components/Steps/Form/SelectedField.tsx b/src/components/Steps/Form/SelectedField.tsx new file mode 100644 index 0000000..dcc27ae --- /dev/null +++ b/src/components/Steps/Form/SelectedField.tsx @@ -0,0 +1,39 @@ +import styles from "@/styles/Home.module.css"; +import { MyForm, MyFormKey } from "@/types/FormTypes"; +import { OptionType } from "@/types/types"; +import { Control, Controller } from "react-hook-form"; +import Select from "react-select"; +interface SelectFieldProps { + control: Control; + options: OptionType[]; + name_: MyFormKey; + placeholder?: string; +} + +const SelectField = ({ + control, + options, + name_, + placeholder, +}: SelectFieldProps) => { + return ( + ( + + - setStudentData({ - ...studentData, - program: selectedOption, - }) - } - instanceId="programSelect" - isSearchable - placeholder="Program" - /> - - setStudentData({ - ...studentData, - grade: selectedOption, - }) - } - instanceId="gradeSelect" - isSearchable - placeholder="Grade" - /> - - setStudentData({ - ...studentData, - stream: selectedOption, - }) - } - instanceId="streamSelect" - isSearchable - placeholder="Stream" /> + + + + diff --git a/src/components/Steps/TestDetails.tsx b/src/components/Steps/TestDetails.tsx index 593d18d..c999c86 100644 --- a/src/components/Steps/TestDetails.tsx +++ b/src/components/Steps/TestDetails.tsx @@ -1,10 +1,9 @@ -import { MouseEvent, useState } from "react"; import styles from "../../styles/Home.module.css"; import { Step } from "@/pages/SessionCreator"; +import { MyForm } from "@/types/FormTypes"; import { ActiveFormProps } from "@/types/types"; -import Select from "react-select"; -import { OptionType } from "../Options/StudentDetailsOptions"; +import { SubmitHandler, useForm } from "react-hook-form"; import { MarkingSchemeOptions, OptionalLimitOptions, @@ -13,127 +12,96 @@ import { TestPurposeOptions, TestTypeOptions, } from "../Options/TestDetailsOptions"; +import SelectField from "./Form/SelectedField"; // Renders sub-page containing test details -export function TestDetails({ setActiveStep, setData }: ActiveFormProps) { - const [testData, setTestData] = useState<{ - [key: string]: OptionType | null; - }>({ - testType: null, - testFormat: null, - testPurpose: null, - testPlatform: null, - markingScheme: null, - optionalLimit: null, +export function TestDetails({ data, setActiveStep, setData }: ActiveFormProps) { + const { register, handleSubmit, control } = useForm({ + defaultValues: { ...data.test }, }); - const handleClick = (e: MouseEvent) => { - e.preventDefault(); - setData((prevData: Object) => ({ ...prevData, testData })); + const onSubmit: SubmitHandler = (test) => { + setData((prevData) => ({ ...prevData, test })); + setActiveStep(Step.TIMELINE); }; - return ( <>
-
- - + + - setTestData({ - ...testData, - testType: selectedOption, - }) - } - instanceId="test_typeSelect" - isSearchable placeholder="Test Type" /> - - setTestData({ - ...testData, - testPurpose: selectedOption, - }) - } - instanceId="test_purposeSelect" - isSearchable placeholder="Test Purpose" /> - + - setTestData({ - ...testData, - markingScheme: selectedOption, - }) - } - isSearchable - instanceId="marking_schemeSelect" - placeholder="Marking Scheme" + placeholder="Optional Limit" /> - - + +
diff --git a/src/components/Steps/Timeline.tsx b/src/components/Steps/Timeline.tsx index c19b7a1..1fbf77d 100644 --- a/src/components/Steps/Timeline.tsx +++ b/src/components/Steps/Timeline.tsx @@ -1,138 +1,121 @@ -import { MouseEvent, useState } from "react"; -import styles from "../../styles/Home.module.css"; - import { Step } from "@/pages/SessionCreator"; +import { MyForm } from "@/types/FormTypes"; import { ActiveFormProps } from "@/types/types"; -import Select from "react-select"; -import { OptionType } from "../Options/StudentDetailsOptions"; +import { SubmitHandler, useForm } from "react-hook-form"; import { HasSyncedOptions, IsEnabledOptions, SessionTypeOptions, } from "../Options/TimelineOptions"; +import SelectField from "./Form/SelectedField"; export default function Timeline({ + data, setActiveStep, setData, createSession, }: ActiveFormProps) { - const [timelineData, setTimelineData] = useState<{ - [key: string]: OptionType | null; - }>({ - isEnabled: null, - sessionType: null, - synced: null, + const { register, handleSubmit, control, reset } = useForm({ + defaultValues: { ...data.timeline }, }); - const handleClick = (e: MouseEvent) => { - e.preventDefault(); - setData((prevData: Object) => ({ ...prevData, timelineData })); + const onSubmit: SubmitHandler = (timeline) => { + setData((prevData) => ({ ...prevData, timeline })); createSession!(); + reset(); }; - return ( - <> -
- -
-
-

Start Date

- -

End Date

- -
-
-
-

Start Time

+ return ( +
+ +
+
+ -

End Time

+
- - setTimelineData({ - ...timelineData, - sessionType: selectedOption, - }) - } - instanceId="session_typeSelect" - isSearchable - placeholder="Sessions Type" - /> - +

End Time

+
-
- - -
- -
- + + + + + + +
+ + +
+ +
); } diff --git a/src/components/displayTable/DataDisplay.tsx b/src/components/displayTable/DataDisplay.tsx index dcb64a5..d641350 100644 --- a/src/components/displayTable/DataDisplay.tsx +++ b/src/components/displayTable/DataDisplay.tsx @@ -3,26 +3,30 @@ import TableRow from "./Row"; const DataDisplay = ({ data }: { data: RowType[] }) => { return ( - - - - - - - - - - - - - - - - {data.map((row, i) => ( - - ))} - -
S.NoBatchTest NameStart DateEnd DateTest TakerReport LinkTest LinkActions
+
+
+ + + + + + + + + + + + + + + + {data.map((row, i) => ( + + ))} + +
S.NoBatchTest NameStart DateEnd DateTest TakerReport LinkTest LinkActions
+
+
); }; diff --git a/src/components/displayTable/Row.tsx b/src/components/displayTable/Row.tsx index 2bdafbd..9e7e779 100644 --- a/src/components/displayTable/Row.tsx +++ b/src/components/displayTable/Row.tsx @@ -1,107 +1,55 @@ import { RowType } from "@/types/types"; import { useState } from "react"; +import { Copy, Edit, Trash2 } from "react-feather"; const TableRow = ({ row, index }: { row: RowType; index: number }) => { const [isExpand, setIsExpand] = useState(false); const { - studentData: { batch }, - testData: { testName, testLink, testTaker }, - timelineData: { reportLink, startDate, endDate }, + student: { batch, testTakers }, + test: { name, sessionLink }, + timeline: { reportLink, startDate, endDate }, } = row!; return ( <> - setIsExpand(!isExpand)}> - {index} - {typeof batch === "object" && batch!.value} - {typeof testName === "string" && testName} - {typeof startDate === "string" && startDate} - {typeof endDate === "string" && endDate} - {typeof testTaker === "string" && testTaker} - {typeof reportLink === "string" && reportLink} - {typeof testLink === "string" && testLink} - -
- - - -
-
- - - -
-
- - - -
+ setIsExpand(!isExpand)}> + {index} + {batch} + {name} + {startDate} + {endDate} + {testTakers} + {reportLink} + {sessionLink} + + { + e.stopPropagation(); + console.log("copy"); + }} + /> + { + e.stopPropagation(); + console.log("edit"); + }} + /> + { + e.stopPropagation(); + console.log("delete"); + }} + /> + {/* Collabsable Container */} {isExpand && ( - -
- {/* The collapsible content goes here */} -
-
Test_type
-
test_format
-
test_purpose
-
- -
-
Test Takers Count
-
optional_limits
-
is_enabled
-
- -
-
date_created
-
start_time
-
end_time
-
- -
-
infinite sessions
-
has_synced
-
repeat_schedule
-
-
- +
Helllo world
)} diff --git a/src/pages/SessionCreator.tsx b/src/pages/SessionCreator.tsx index a7ef012..50ae2a9 100644 --- a/src/pages/SessionCreator.tsx +++ b/src/pages/SessionCreator.tsx @@ -2,6 +2,7 @@ import Stepper from "@/components/Stepper"; import StudentDetails from "@/components/Steps/StudentDetails"; import { TestDetails } from "@/components/Steps/TestDetails"; import Timeline from "@/components/Steps/Timeline"; +import { RowType } from "@/types/types"; import { useRouter } from "next/router"; import { useState } from "react"; @@ -21,28 +22,44 @@ const stepArr: string[] = [ export default function SessionCreator() { const router = useRouter(); const [activeStep, setActiveStep] = useState(Step.STUDENT_DETAILS); - const [data, setData] = useState({}); + const [data, setData] = useState({ + student: {}, + test: {}, + timeline: {}, + }); + console.log(data!); - console.log(data); - - const submitData = () => { + const createSession = () => { console.log(data!); // TODO: POST DATA FUNCTION HERE - setTimeout(() => router.push("/"), 2000); + // setTimeout(() => router.push('/'), 2000); }; const activeForm = () => { if (activeStep === Step.STUDENT_DETAILS) { - return ; + return ( + + ); } else if (activeStep === Step.TEST_DETAILS) { - return ; + return ( + + ); } else { return ( ); } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 02aa8c1..ffcd772 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,4 +1,3 @@ -import Button from "@/components/Buttons/Button"; import DataDisplay from "@/components/displayTable/DataDisplay"; import { data } from "@/utils/data"; // import { Inter } from "next/font/google"; @@ -6,7 +5,7 @@ import Head from "next/head"; import { useRouter } from "next/router"; // const inter = Inter({ subsets: ["latin"] }); -// TODO: Will Fetch data from the server using axios +// TODO: Fetch data from the server using axios export default function Home() { const router = useRouter(); @@ -21,10 +20,9 @@ export default function Home() {