From a938de76b68b938a36e24e2c5e78830456a3e39d Mon Sep 17 00:00:00 2001 From: Brandon Egger Date: Tue, 11 Apr 2023 00:52:51 -0500 Subject: [PATCH] refactor survey to have simplified user experience --- src/components/Survey.tsx | 212 +++++++++++++++++++++++++++++++++ src/pages/resources/survey.tsx | 44 ++++--- tailwind.config.cjs | 7 +- 3 files changed, 239 insertions(+), 24 deletions(-) create mode 100644 src/components/Survey.tsx diff --git a/src/components/Survey.tsx b/src/components/Survey.tsx new file mode 100644 index 0000000..c3e26f6 --- /dev/null +++ b/src/components/Survey.tsx @@ -0,0 +1,212 @@ +import { type PaymentType, type Platform, type Skill, type SkillLevel } from "@prisma/client" +import { type Dispatch, type SetStateAction, useState, useEffect } from "react"; + +export type QuestionTypes = Platform | Skill | SkillLevel | PaymentType | string; + +export interface Option { + label: string, + value: T, +} + +export interface Question { + for: string, + header: string, + question: string, + optional: true, + options: Option[] +} + +const GreetingPage = ({updatePage}: { + updatePage: (pageNumber: number) => void, +}) => { + const getStartedClick = () => { + updatePage(1); + } + + return ( +
+

Welcome to the resources survey!

+

We will ask a few questions about the patient and then recommend the best resources based on your answers!

+ +
+ ) +} + +/** + * Single question component for a guided survey + */ +const QuestionPage = ({isLastPage, page, question, updatePage, formData, updateFormData, submitForm}: { + isLastPage: boolean, + page: number, + question: Question, + updatePage: (pageNumber: number) => void, + formData: Record, + updateFormData: Dispatch>>, +}) => { + const OptionToggle = ({option}: {option: Option}) => { + const selected = formData[question.for]?.includes(option.value) ?? false; + + const handleToggle = () => { + const newFormData = { + ...formData + }; + + if (!newFormData[question.for]) { + newFormData[question.for] = [option.value]; + } else if (newFormData[question.for]?.includes(option.value)) { + newFormData[question.for] = newFormData[question.for]?.filter(function(item) { + return item !== option.value + }) ?? []; + } else { + newFormData[question.for] = [...newFormData[question.for] ?? [], option.value]; + } + + updateFormData(newFormData); + } + + return ( + + ) + } + + useEffect(() => { + if (!formData[question.for]) { + const newFormData = {...formData}; + newFormData[question.for] = []; + + updateFormData(newFormData); + } + }); + + const nextClick = () => { + updatePage(page + 1); + } + + const backClick = () => { + updatePage(page - 1); + } + + const AdvanceButtons = () => { + return ( +
+ {!isLastPage ? +
+ + +
+ : +
+ + +
+ } +
+ ) + }; + + const htmlOptions: JSX.Element[] = [] + const optionButtons: JSX.Element[] = [] + + question.options.forEach((option, index) => { + optionButtons.push() + htmlOptions.push() + }); + + return ( +
+
+

+

{question.question}

+
+ + {/** Hidden selector html */} + + +
+ {optionButtons} +
+ +
+ ) +} + +const PageTransition = ({lastPage, currentPage}: { + lastPage: JSX.Element | null, + currentPage: JSX.Element, +}) => { + return ( +
+
+ {currentPage} +
+ + {/** last page */} +
+ {lastPage} +
+
+ ); +}; + +/** + * Main guided survey component. + * Page 0 = greeting page. + */ +const GuidedSurvey = ({questions}: { + questions: Question[], +}) => { + const [page, setPage] = useState(0); + const [formData, setFormData] = useState<(Record)>({}); + const [previousPage, setPreviousPage] = useState(undefined); + + const updatePage = (pageNumber: number) => { + setPreviousPage(page); + setPage(pageNumber); + }; + + const SurveyPage = ({pageNumber}: { + pageNumber?: number, + }) => { + if (pageNumber === undefined) { + return null; + } + + if (pageNumber === 0) { + return ( + + ); + } + + const question = questions[pageNumber]; + if (!question) { + return null; + } + + const isLastPage = pageNumber === questions.length - 1 + + return ( + + ); + } + + const lastPage = ; + const currentPage = ; + + return ( +
+
+

Search

+
+ + +
+ ) +} + +export { + GuidedSurvey, +} diff --git a/src/pages/resources/survey.tsx b/src/pages/resources/survey.tsx index 6c7ff8d..2a757d0 100644 --- a/src/pages/resources/survey.tsx +++ b/src/pages/resources/survey.tsx @@ -1,25 +1,12 @@ -import { type PaymentType, type Platform, type Skill, type SkillLevel } from "@prisma/client" import { type Dispatch, type SetStateAction, useEffect, useState } from "react"; - -type QuestionTypes = Platform | Skill | SkillLevel | PaymentType | string; - -interface Option { - label: string, - value: T, -} - -interface Question { - for: string, - header: string, - question: string, - options: Option[] -} +import { GuidedSurvey, type Question, type QuestionTypes, type Option } from "~/components/Survey"; const questions: Question[] = [ { for: "ages", header: "Age of Patient", question: "How old is the patient?", + optional: true, options: [ { label: "Child (0-10)", @@ -39,6 +26,7 @@ const questions: Question[] = [ for: "platforms", header: "Desired Platforms", question: "What platform(s) does the resource need to be on?", + optional: true, options: [ { label: "Apple (iOS)", @@ -62,6 +50,7 @@ const questions: Question[] = [ for: "skill_levels", header: "Skill Level", question: "What skill level(s) should the resource have?", + optional: true, options: [ { label: "Beginner", @@ -81,6 +70,7 @@ const questions: Question[] = [ for: "skills", header: "Skills Practiced", question: "What skill(s) would you like the resource to cover?", + optional: true, options: [ { label: "Phonemes", @@ -185,17 +175,25 @@ const SearchForm = ({questions}: {questions: Question[]}) => { ) } +// const SearchPage = () => { +// return <> +//
+//
+//

Search

+//
+//
+// +//
+//
+// +// } + const SearchPage = () => { - return <> + return (
-
-

Search

-
-
- -
+
- + ) } export default SearchPage \ No newline at end of file diff --git a/tailwind.config.cjs b/tailwind.config.cjs index b41304d..94d5bd3 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -8,10 +8,15 @@ const config = { '0%, 100%': { transform: 'scale(1)' }, '50%': { transform: 'scale(1.1)' }, }, + slide_left_full: { + '0%': { transform: 'translate(0%)' }, + '100%': { transform: 'translate(-50%)' }, + } }, animation: { expand_in_out: 'expand_in_out 2s ease-in-out infinite', - } + slide_survey_page: 'slide_left_full 1s ease-in-out', + }, }, }, plugins: [],