Skip to content

Commit

Permalink
Feature/Rate type question
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryczko authored Sep 19, 2023
1 parent 4e48325 commit 2007a94
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 1 deletion.
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,5 @@ enum QuestionType {
EMOJI
INPUT
CHOICE
RATE
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Button, {
ButtonVariant,
} from 'shared/components/Button/Button';
import useTranslation from 'next-translate/useTranslation';
import RateAnswersComponent from 'features/surveys/components/AnswersComponent/RateComponent/RateComponent';

interface AnswersComponentFactoryProps {
type: QuestionType;
Expand Down Expand Up @@ -43,6 +44,7 @@ export const AnswersComponentFactory = (
{type === QuestionType.EMOJI && <ListAnswersComponent {...props} />}
{type === QuestionType.INPUT && <TextAnswersComponent {...props} />}
{type === QuestionType.CHOICE && <ChoiceComponent {...props} />}
{type === QuestionType.RATE && <RateAnswersComponent {...props} />}

{(isNextButtonVisible || isBackButtonVisible) && (
<div className="mt-6 flex flex-col gap-x-4 gap-y-2 sm:flex-row">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { useState } from 'react';
import useTranslation from 'next-translate/useTranslation';
import StarComponent from 'features/surveys/components/AnswersComponent/RateComponent/StarComponent/StarComponent';
import clsx from 'clsx';

interface RateAnswersComponentProps {
handleAnswerChange: (answer: string, questionId: string) => void;
answer?: string;
questionId: string;
isSubmitted: boolean;
isRequired: boolean;
}

export default function RateAnswersComponent({
handleAnswerChange,
answer,
questionId,
isSubmitted,
isRequired,
}: RateAnswersComponentProps) {
const { t } = useTranslation('survey');

const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);

return (
<>
<div className="flex items-center justify-center">
{[...Array(5)].map((_, index) => (
<StarComponent
key={index}
classNames={clsx(
answer && index < +answer ? 'text-yellow-400' : 'text-gray-300',
hoveredIndex !== null
? hoveredIndex >= index
? '!text-yellow-400'
: '!text-gray-300'
: ''
)}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
onClick={() =>
handleAnswerChange((index + 1).toString(), questionId)
}
/>
))}
</div>
{isSubmitted && !answer && isRequired && (
<p className="mt-4 text-sm text-red-500">{t('requiredField')}</p>
)}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import clsx from 'clsx';
import React from 'react';

interface StarComponentProps {
classNames?: string;
onMouseEnter: () => void;
onMouseLeave: () => void;
onClick: () => void;
}

export default function StarComponent({
classNames,
onMouseEnter,
onMouseLeave,
onClick,
}: StarComponentProps) {
return (
<div
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
className="cursor-pointer px-1"
onClick={onClick}
>
<svg
className={clsx('h-5 w-5', classNames)}
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 22 20"
>
<path d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import NewQuestionModalButton from 'features/surveys/components/NewQuestionModal
import EmojiIcon from 'shared/components/QuestionTypeIcons/EmojiIcon';
import InputIcon from 'shared/components/QuestionTypeIcons/InputIcon';
import ChoiceIcon from 'shared/components/QuestionTypeIcons/ChoiceIcon';
import RateIcon from 'shared/components/QuestionTypeIcons/RateIcon';

type NewQuestionModalProps = {
isOpened: boolean;
Expand Down Expand Up @@ -59,6 +60,17 @@ export default function NewQuestionModal({
});
};

const addRateQuestion = () => {
closeModal();
onSuccess?.({
id: v4(),
type: QuestionType.RATE,
title: '',
isRequired: true,
expanded: true,
});
};

return (
<StyledDialog
isOpen={isOpened}
Expand All @@ -81,6 +93,11 @@ export default function NewQuestionModal({
icon={<ChoiceIcon />}
text="Choice"
/>
<NewQuestionModalButton
onClick={addRateQuestion}
icon={<RateIcon />}
text="Rate"
/>
</div>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import QuestionBlockWrapper from 'features/surveys/components/QuestionBlocks/Que
import InputQuestionBlock from 'features/surveys/components/QuestionBlocks/InputQuestionBlock/InputQuestionBlock';
import ChoiceQuestionBlock from 'features/surveys/components/QuestionBlocks/ChoiceQuestionBlock/ChoiceQuestionBlock';
import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
import RateQuestionBlock from 'features/surveys/components/QuestionBlocks/RateQuestionBlock/RateQuestionBlock';

interface QuestionBlockFactoryProps {
type: QuestionType;
Expand Down Expand Up @@ -69,6 +70,7 @@ export default function QuestionBlockFactory({
expandQuestion={expandQuestion}
type={type}
>
{type === QuestionType.RATE && <RateQuestionBlock />}
{type === QuestionType.INPUT && <InputQuestionBlock />}
{type === QuestionType.CHOICE && (
<ChoiceQuestionBlock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { QuestionType } from '@prisma/client';
import EmojiIcon from 'shared/components/QuestionTypeIcons/EmojiIcon';
import InputIcon from 'shared/components/QuestionTypeIcons/InputIcon';
import ChoiceIcon from 'shared/components/QuestionTypeIcons/ChoiceIcon';
import RateIcon from 'shared/components/QuestionTypeIcons/RateIcon';

interface QuestionBlockWrapperProps {
index: number;
Expand Down Expand Up @@ -93,6 +94,7 @@ export default function QuestionBlockWrapper({
{type === QuestionType.EMOJI && <EmojiIcon />}
{type === QuestionType.INPUT && <InputIcon />}
{type === QuestionType.CHOICE && <ChoiceIcon />}
{type === QuestionType.RATE && <RateIcon />}
</div>

<div className=" w-full grow">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function RateQuestionBlock() {
return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ export default function ResultComponent({
}, [notEmptyAnswers]);

useEffect(() => {
if (type === QuestionType.EMOJI || type === QuestionType.CHOICE) {
if (
type === QuestionType.EMOJI ||
type === QuestionType.CHOICE ||
type === QuestionType.RATE
) {
const chartData = getDataToChart();
setChartData(chartData);
}
Expand All @@ -74,6 +78,7 @@ export default function ResultComponent({
{type === QuestionType.EMOJI && <BarChart data={chartData} emojiLabels />}
{type === QuestionType.INPUT && <TextResults answers={notEmptyAnswers} />}
{type === QuestionType.CHOICE && <BarChart data={chartData} />}
{type === QuestionType.RATE && <BarChart data={chartData} />}
</div>
);
}
6 changes: 6 additions & 0 deletions src/shared/components/QuestionTypeIcons/RateIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { StarIcon } from '@heroicons/react/solid';
import React from 'react';

export default function RateIcon() {
return <StarIcon />;
}

1 comment on commit 2007a94

@vercel
Copy link

@vercel vercel bot commented on 2007a94 Sep 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

formslab – ./

formslab-git-main-ryczko.vercel.app
formslab-ryczko.vercel.app
formslab.vercel.app

Please sign in to comment.