Skip to content

Commit

Permalink
Feature/Collapse questions (#211)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryczko authored Aug 21, 2023
1 parent a84153c commit f6ffb42
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 104 deletions.
2 changes: 0 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ module.exports = {
'next/core-web-vitals',
'plugin:jest/recommended',
'plugin:testing-library/react',
'plugin:jsx-a11y/recommended',
'plugin:tailwindcss/recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
Expand All @@ -33,7 +32,6 @@ module.exports = {
plugins: [
'react',
'react-hooks',
'jsx-a11y',
'jest',
'testing-library',
'tailwindcss',
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
"eslint-plugin-cypress": "^2.13.3",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-no-relative-import-paths": "^1.5.2",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function EmojiPicker({
<div>
<button
type="button"
className="label-text flex min-h-[57px] w-16 items-center justify-center rounded-lg bg-white p-3 shadow transition hover:scale-95"
className="label-text flex min-h-[57px] w-16 items-center justify-center rounded-md bg-white p-3 shadow transition hover:scale-95"
onClick={() => setDisplayPicker(!displayPicker)}
>
{!addEmoji ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default function NewQuestionModal({
':slightly_frowning_face:',
':rage:',
],
expanded: true,
});
};

Expand All @@ -38,7 +39,8 @@ export default function NewQuestionModal({
id: v4(),
type: QuestionType.INPUT,
title: '',
isRequired: false,
isRequired: true,
expanded: true,
});
};

Expand All @@ -48,8 +50,9 @@ export default function NewQuestionModal({
id: v4(),
type: QuestionType.CHOICE,
title: '',
isRequired: false,
isRequired: true,
options: ['', '', ''],
expanded: true,
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ export default function ChoiceQuestionBlock({
};

return (
<div className="mt-2">
<div>
{options.map((option, index) => (
<div className="flex w-full" key={index}>
<div className="mr-4 block flex-grow">
<div className="flex w-full gap-2" key={index}>
<div className="block flex-grow">
<Input
type="text"
value={option}
placeholder="Answer..."
error={getAnswerError(option)}
className="mt-[2px]"
onChange={(e) =>
handleOptionChange(
index,
Expand All @@ -61,7 +62,7 @@ export default function ChoiceQuestionBlock({
</div>
{options.length > MIN_OPTIONS && (
<Button
className="mt-[8px] h-[44px] w-[60px]"
className="mt-[2px] h-[42px] w-[42px]"
variant={ButtonVariant.DANGER}
icon={<TrashIcon className="h-4 w-4" />}
onClick={() => handleOptionRemove(index, questionIndex)}
Expand All @@ -70,7 +71,7 @@ export default function ChoiceQuestionBlock({
</div>
))}
{options.length < MAX_OPTIONS && (
<div className="mt-2">
<div className="mb-3 mt-2">
<Button
className="ml-auto"
onClick={() => handleAddingNewOption('', questionIndex)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ interface QuestionBlockFactoryProps {
updateQuestionRequired: (questionIndex: number) => void;
isRequired: boolean;
dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
expanded: boolean;
expandQuestion: (questionIndex: number) => void;
}

export default function QuestionBlockFactory({
Expand All @@ -48,6 +50,8 @@ export default function QuestionBlockFactory({
updateQuestionRequired,
isDraggingPossible,
dragHandleProps,
expanded,
expandQuestion,
}: QuestionBlockFactoryProps) {
return (
<QuestionBlockWrapper
Expand All @@ -61,6 +65,8 @@ export default function QuestionBlockFactory({
isDraggingPossible={isDraggingPossible}
isRequired={isRequired}
updateQuestionRequired={updateQuestionRequired}
expanded={expanded}
expandQuestion={expandQuestion}
>
{type === QuestionType.INPUT && <InputQuestionBlock />}
{type === QuestionType.CHOICE && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { SelectorIcon, TrashIcon } from '@heroicons/react/outline';
import {
ChevronDownIcon,
SelectorIcon,
TrashIcon,
} from '@heroicons/react/outline';
import { ChangeEvent, PropsWithChildren } from 'react';
import Input from 'shared/components/Input/Input';
import useTranslation from 'next-translate/useTranslation';
import { MAX_QUESTION_LENGTH } from 'shared/constants/surveysConfig';
import Toggle from 'shared/components/Toggle/Toggle';
import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
import clsx from 'clsx';

interface QuestionBlockWrapperProps {
index: number;
Expand All @@ -17,6 +22,8 @@ interface QuestionBlockWrapperProps {
updateQuestionRequired: (questionIndex: number) => void;
isRequired: boolean;
dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
expanded: boolean;
expandQuestion: (questionIndex: number) => void;
}

export default function QuestionBlockWrapper({
Expand All @@ -31,6 +38,8 @@ export default function QuestionBlockWrapper({
updateQuestionRequired,
dragHandleProps,
isDraggingPossible,
expanded,
expandQuestion,
}: PropsWithChildren<QuestionBlockWrapperProps>) {
const { t } = useTranslation('surveyCreate');

Expand All @@ -54,50 +63,73 @@ export default function QuestionBlockWrapper({
return undefined;
};

const onExpand = () => {
expandQuestion(index);
};

return (
<div className="relative rounded-md border bg-white/30 p-4 pr-8 shadow-sm">
<div className="absolute right-0 top-0 translate-x-[50%] translate-y-[-15%] space-y-1 px-1">
{isRemovingPossible && (
<div className="relative overflow-hidden rounded-md border bg-white/30 shadow-sm">
<div className="flex flex-col items-start gap-1 px-3 pb-1 pt-3 sm:flex-row sm:gap-2">
<div className="flex w-full items-start gap-2">
<button
onClick={removeQuestion}
className="cursor-pointer rounded-md bg-white p-[6px] shadow-md hover:scale-95"
onClick={onExpand}
className="cursor-pointer rounded-md border border-opacity-100 p-[13px]"
>
<TrashIcon className="w-[16px] text-red-700" />
<ChevronDownIcon
className={clsx(
'w-[15px] transition-transform',
!expanded && '-rotate-90'
)}
/>
</button>
)}

{isDraggingPossible && (
<div
className="cursor-pointer rounded-md bg-white p-[6px] shadow-md hover:scale-95"
{...dragHandleProps}
>
<SelectorIcon className="w-[16px]" />
<div className="w-full grow">
<Input
placeholder={t('questionPlaceholder')}
onInput={handleQuestionChange}
value={questionTitle}
error={questionError()}
className="mt-0"
maxLength={MAX_QUESTION_LENGTH}
data-test-id={`question-input-${index}`}
/>
</div>
)}
</div>

<div className="flex flex-col items-start gap-2 sm:flex-row sm:gap-4">
<div className="w-full grow">
<Input
placeholder={t('questionPlaceholder')}
onInput={handleQuestionChange}
className="mt-2"
value={questionTitle}
error={questionError()}
maxLength={MAX_QUESTION_LENGTH}
data-test-id={`question-input-${index}`}
/>
</div>
<div className="flex w-full justify-center sm:w-auto">
<Toggle
classNames="sm:mt-4"
label={t('requiredToggle')}
onToggle={handleRequiredToggle}
isEnabled={isRequired}
/>

<div className="mb-2 flex w-full items-start justify-end gap-2 sm:w-auto">
{isDraggingPossible && (
<div
className="cursor-pointer rounded-md border bg-white p-[13px] shadow-sm hover:scale-95"
{...dragHandleProps}
>
<SelectorIcon className="w-[15px]" />
</div>
)}
{isRemovingPossible && (
<button
onClick={removeQuestion}
className="cursor-pointer rounded-md border bg-white p-[13px] shadow-sm hover:scale-95"
>
<TrashIcon className="w-[15px] text-red-700" />
</button>
)}
</div>
</div>
{children}

{expanded && (
<div className="mb-4 px-3">
{children}

<div className="mt-2 flex justify-end border-t">
<Toggle
classNames="mt-4"
label={t('requiredToggle')}
onToggle={handleRequiredToggle}
isEnabled={isRequired}
/>
</div>
</div>
)}
</div>
);
}
2 changes: 2 additions & 0 deletions src/features/surveys/managers/createSurveyManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const setUp = () => {
title: NEW_QUESTION_TITLE,
options: [],
isRequired: false,
expanded: true,
});
});

Expand All @@ -35,6 +36,7 @@ describe('useCreateSurveyManager tests', () => {
title: 'test',
options: [],
isRequired: false,
expanded: true,
});
});

Expand Down
34 changes: 30 additions & 4 deletions src/features/surveys/managers/createSurveyManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface Question {
options?: string[];
type: QuestionType;
isRequired: boolean;
expanded: boolean;
}

export const useCreateSurveyManager = () => {
Expand Down Expand Up @@ -134,6 +135,17 @@ export const useCreateSurveyManager = () => {
};

const areQuestionsValid = (questions: Question[]) => {
console.log('jkljkljl');
setQuestions((oldQuestions) =>
oldQuestions.map((question) => {
console.log(question);
if (question.options?.includes('')) {
return { ...question, expanded: true };
}
return question;
})
);

if (
questions.some(
(question) => question.options?.includes('') || question.title === ''
Expand All @@ -146,19 +158,22 @@ export const useCreateSurveyManager = () => {

const isSurveyValid = () => {
setIsSubmitted(true);
let isValid = true;

if (!isTitleValid(title)) {
toast.error(t('fillRequiredFields'));
setError(t('required'));
return false;
isValid = false;
}

if (!areQuestionsValid(questions)) {
isValid = false;
}

if (!isValid) {
toast.error(t('fillRequiredFields'));
return false;
}

return true;
return isValid;
};

const createSurvey = async () => {
Expand Down Expand Up @@ -204,6 +219,16 @@ export const useCreateSurveyManager = () => {
setQuestions(newOrderedQuestions);
};

const expandQuestion = (questionIndex: number) => {
setQuestions((oldQuestions) => {
const newQuestions = [...oldQuestions];
const newQuestion = { ...newQuestions[questionIndex] };
newQuestion.expanded = !newQuestion.expanded;
newQuestions.splice(questionIndex, 1, newQuestion);
return newQuestions;
});
};

return {
title,
error,
Expand All @@ -220,5 +245,6 @@ export const useCreateSurveyManager = () => {
isSubmitted,
updateQuestionRequired,
reorderQuestion,
expandQuestion,
};
};
Loading

0 comments on commit f6ffb42

Please sign in to comment.