From c49619ec42117799c727a3bfacb095aee9332eb3 Mon Sep 17 00:00:00 2001 From: leonleerl Date: Wed, 15 Jan 2025 02:56:53 +0000 Subject: [PATCH 1/5] feat(question): add Preview Modal --- client/package-lock.json | 78 +++++++++----- client/package.json | 3 +- .../components/ui/Question/preview-modal.tsx | 100 ++++++++++++++++++ client/src/pages/question/create.tsx | 83 +++++++++++---- client/src/types/app-sidebar.ts | 4 +- client/src/types/question.ts | 24 ++++- 6 files changed, 239 insertions(+), 53 deletions(-) create mode 100644 client/src/components/ui/Question/preview-modal.tsx diff --git a/client/package-lock.json b/client/package-lock.json index ffb24c2..d34f930 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -16,6 +16,7 @@ "@radix-ui/react-separator": "^1.1.1", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tooltip": "^1.1.6", + "@radix-ui/react-visually-hidden": "^1.1.1", "@tanstack/react-query": "^5.51.23", "@tanstack/react-query-devtools": "^5.51.23", "@types/js-cookie": "^3.0.6", @@ -1580,6 +1581,29 @@ } } }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-separator": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.1.tgz", @@ -1843,29 +1867,6 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", - "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", @@ -1984,12 +1985,35 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", - "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", + "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", diff --git a/client/package.json b/client/package.json index df68f75..5fc4054 100644 --- a/client/package.json +++ b/client/package.json @@ -16,14 +16,15 @@ "check-all": "npm run lint && npm run format:check && npm run typecheck" }, "dependencies": { - "@radix-ui/react-collapsible": "^1.1.2", "@hookform/resolvers": "^3.9.1", + "@radix-ui/react-collapsible": "^1.1.2", "@radix-ui/react-dialog": "^1.1.4", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-separator": "^1.1.1", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tooltip": "^1.1.6", + "@radix-ui/react-visually-hidden": "^1.1.1", "@tanstack/react-query": "^5.51.23", "@tanstack/react-query-devtools": "^5.51.23", "@types/js-cookie": "^3.0.6", diff --git a/client/src/components/ui/Question/preview-modal.tsx b/client/src/components/ui/Question/preview-modal.tsx new file mode 100644 index 0000000..5750e51 --- /dev/null +++ b/client/src/components/ui/Question/preview-modal.tsx @@ -0,0 +1,100 @@ +import * as VisuallyHidden from "@radix-ui/react-visually-hidden"; +import { useEffect, useState } from "react"; + +import { + Dialog, + DialogContent, + DialogDescription, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { PreviewModalProps } from "@/types/question"; + +import { Button } from "../button"; +import { MathInput } from "../math-input"; + +export default function PreviewModal({ + children, + dataContext, + onClose, +}: PreviewModalProps) { + const [question, setQuestion] = useState(dataContext.question); + const [isSolutionVisible, setIsSolutionVisible] = useState(true); + + const handleSolutionVisible = () => { + setIsSolutionVisible(!isSolutionVisible); + }; + + // When close button is clicked, bring the modified question data back to Create page + const handleDialogClose = () => { + onClose(question); + }; + + useEffect(() => { + if (dataContext?.question) { + setQuestion(dataContext.question); + } + }, [dataContext]); + return ( + <> + + {children} + + + Preview Data + + + +
+ {/* Question */} +
+
+ {dataContext.questionName} + [{dataContext.mark} marks] +
+

+ { + setQuestion(e.target.value); + }} + > +
+ {/* Solution */} +
+

Solution

+
+

+ Answer:{" "} + {dataContext.answer} +

+

{dataContext.solution}

+
+
+ + {/* Bottom buttons */} +
+ + + + +
+
+
+
+ + ); +} diff --git a/client/src/pages/question/create.tsx b/client/src/pages/question/create.tsx index 97f4013..60ceaa5 100644 --- a/client/src/pages/question/create.tsx +++ b/client/src/pages/question/create.tsx @@ -1,6 +1,6 @@ import { zodResolver } from "@hookform/resolvers/zod"; -import React from "react"; -import { useForm } from "react-hook-form"; +import React, { useState } from "react"; +import { useForm, useWatch } from "react-hook-form"; import { z } from "zod"; import { Button } from "@/components/ui/button"; @@ -14,6 +14,7 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import PreviewModal from "@/components/ui/Question/preview-modal"; import { Select, SelectContent, @@ -42,7 +43,7 @@ const formSchema = z.object({ ), { message: - "Answers must be integers between 0-999, separated by commas without spaces.", + "Must be an integer from 0-999, use “,” to separate multiple answers", }, ), solution: z.string().optional(), @@ -70,28 +71,40 @@ export default function Create() { }, }); - const onSubmit = (data: FormValues) => { + const watchedValues = useWatch({ + control: form.control, + }); + + const handleSubmit = (data: FormValues) => { console.log("Form Data:", data); alert(JSON.stringify(data, null, 2)); }; + const handlePreviewClose = (updatedQuestion: string) => { + form.setValue("question", updatedQuestion); + }; + return (

Create Question

- + {/* Question Name */} ( - + Question Name * - + @@ -104,11 +117,12 @@ export default function Create() { control={form.control} render={({ field }) => ( - + Question *