Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cypress/e2e/answerSurvey.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ describe('Answering survey tests', () => {

cy.get('[data-test-id="create-survey"]').click();
cy.url().should('include', '/survey/create');
cy.get('[data-test-id="expand-templates"]').click();
cy.get('[data-test-id="start-from-scratch-field"]').click();
cy.get('[data-test-id="start-from-scratch-button"]').click();
cy.get('[data-test-id="confirm-template-change"]').click();
cy.get('[data-test-id="add-question-button"]').click();
cy.get('[data-test-id="emoji-question-button"]').click();
cy.get('[data-test-id="add-question-button"]').click();
Expand Down
4 changes: 3 additions & 1 deletion cypress/e2e/createSurvey.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ describe('Creating survey tests', () => {
cy.get('[data-test-id="create-survey"]').click();
cy.url().should('include', '/survey/create');

cy.get('[data-test-id="expand-templates"]').click();
cy.get('[data-test-id="start-from-scratch-field"]').click();
cy.get('[data-test-id="start-from-scratch-button"]').click();
cy.get('[data-test-id="confirm-template-change"]').click();

cy.get('[data-test-id="add-question-button"]').click();
cy.get('[data-test-id="emoji-question-button"]').click();
cy.get('[data-test-id="add-question-button"]').click();
Expand Down
22 changes: 4 additions & 18 deletions src/features/surveys/features/SurveyCreator/SurveyCreator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,23 @@ import React from 'react';
import clsx from 'clsx';
import { usePreviewPanelContext } from 'features/surveys/features/SurveyCreator/managers/previewPanelManager/context';
import PreviewPanel from 'features/surveys/features/SurveyCreator/components/PreviewPanel/PreviewPanel';
import { useSurveyCreatorContext } from 'features/surveys/features/SurveyCreator/managers/createSurveyManager/context';

import dynamic from 'next/dynamic';
import CreatorContent from 'features/surveys/features/SurveyCreator/components/CreatorContent/CreatorContent';

const Templates = dynamic(
() =>
import(
'features/surveys/features/SurveyCreator/components/Templates/Templates'
),
{ ssr: false }
);

export default function SurveyCreator() {
const { isPanelOpened } = usePreviewPanelContext();
const { isEditMode, isTemplatePicked } = useSurveyCreatorContext();
const { isPanelOpened, openedWithoutAnimation } = usePreviewPanelContext();

return (
<>
<div
className={clsx(
'flex-grow py-8 transition-all duration-500 ease-in-out',
'flex-grow py-8',
!openedWithoutAnimation && 'transition-all duration-500 ease-in-out',
isPanelOpened && 'xl:mr-[550px]'
)}
>
<div className="mx-auto max-w-[58rem] px-4 xl:px-10">
{!isTemplatePicked && !isEditMode ? (
<Templates />
) : (
<CreatorContent />
)}
<CreatorContent />
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import ActionButtons from 'features/surveys/features/SurveyCreator/components/Ac
import QuestionsSection from 'features/surveys/features/SurveyCreator/components/QuestionsSection/QuestionsSection';
import TitleAndConfigSection from 'features/surveys/features/SurveyCreator/components/TitleAndConfigSection/TitleAndConfigSection';
import withAnimation from 'shared/HOC/withAnimation';
import Templates from 'features/surveys/features/SurveyCreator/components/Templates/Templates';
import { useSurveyCreatorContext } from 'features/surveys/features/SurveyCreator/managers/createSurveyManager/context';

function CreatorContent() {
const { isEditMode } = useSurveyCreatorContext();

return (
<>
{!isEditMode && <Templates />}
<TitleAndConfigSection />
<QuestionsSection />
<ActionButtons />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ import Button from 'shared/components/Button/Button';

export default function PreviewPanel() {
const { questions, title, surveyOptions } = useSurveyCreatorContext();
const { isPanelOpened, togglePanel, handleRestart, restartTrigger } =
usePreviewPanelContext();
const {
isPanelOpened,
togglePanel,
handleRestart,
restartTrigger,
openedWithoutAnimation,
} = usePreviewPanelContext();

return (
<>
Expand All @@ -23,7 +28,9 @@ export default function PreviewPanel() {

<div
className={clsx(
'fixed bottom-0 right-0 top-[var(--navigation-height)] w-[550px] max-w-[calc(100vw-(100vw-100%))] items-center overflow-hidden border-l shadow transition-transform duration-500 ease-in-out',
'fixed bottom-0 right-0 top-[var(--navigation-height)] w-[550px] max-w-[calc(100vw-(100vw-100%))] items-center overflow-hidden border-l shadow',
!openedWithoutAnimation &&
'transition-transform duration-500 ease-in-out',
!isPanelOpened && 'translate-x-full'
)}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,28 @@
import React from 'react';
import { Template } from 'features/surveys/features/SurveyCreator/components/Templates/Templates';
import clsx from 'clsx';
import Button, { ButtonVariant } from 'shared/components/Button/Button';

interface TemplateItemProps {
template?: Template;
title?: string;
onTemplatePreview?: (event: React.MouseEvent<HTMLDivElement>) => void;
onTemplatePick: (event: React.MouseEvent<HTMLButtonElement>) => void;
isInPreview: boolean;
buttonContent?: string;
fieldTestSelector?: string;
buttonTestSelector?: string;
}

export default function TemplateItem({
template,
title,
onTemplatePreview,
onTemplatePick,
isInPreview,
buttonContent,
fieldTestSelector,
buttonTestSelector,
}: TemplateItemProps) {
return (
<div
onClick={(e) => onTemplatePreview?.(e)}
data-test-id={fieldTestSelector}
className={clsx(
'flex h-[140px] flex-grow cursor-pointer flex-col items-center rounded border border-zinc-600/50 px-4 pb-4 shadow',
template ? 'border-solid bg-zinc-50' : 'bg-white',
isInPreview ? 'pt-2' : 'pt-4'
'flex h-[60px] flex-grow cursor-pointer flex-col items-center rounded border border-zinc-300 bg-white px-4 hover:bg-zinc-50'
)}
>
<div className="flex grow items-center">{title || 'Blank'}</div>
{isInPreview && (
<Button
className="w-full"
variant={ButtonVariant.PRIMARY}
onClick={(e) => onTemplatePick(e)}
data-test-id={buttonTestSelector}
>
{buttonContent || 'Use Template'}
</Button>
)}
<div className="flex grow items-center text-sm">
{title || 'Blank form'}
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,122 +4,111 @@ import { useSurveyCreatorContext } from 'features/surveys/features/SurveyCreator
import TemplateItem from 'features/surveys/features/SurveyCreator/components/Templates/TemplateItem';
import { TEMPLATES } from 'features/surveys/features/SurveyCreator/constants/Templates';
import { DraftQuestion } from 'features/surveys/features/SurveyCreator/managers/createSurveyManager/createSurveyManager';
import clsx from 'clsx';
import withAnimation from 'shared/HOC/withAnimation';
import StyledDialog from 'shared/components/StyledDialog/StyledDialog';
import Button, { ButtonVariant } from 'shared/components/Button/Button';
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/outline';

export interface Template {
title: string;
questions: DraftQuestion[];
}

function Templates() {
const { togglePanel, isPanelOpened, handleRestart } =
usePreviewPanelContext();
const { handleRestart } = usePreviewPanelContext();

const {
selectTemplate,
getDraftSurveyFromSessionStorage,
setIsTemplatePicked,
} = useSurveyCreatorContext();
const { selectTemplate } = useSurveyCreatorContext();

const [previewIndex, setPreviewIndex] = useState<number | null>(
getDraftSurveyFromSessionStorage() ? 0 : 1
);

const toggleOnLargeScreen = () => {
if (window.innerWidth > 1280 && !isPanelOpened) {
togglePanel();
}
};

const handleContinueLastSurveyPreview = (
event: React.MouseEvent<HTMLDivElement>
) => {
event.stopPropagation();
const draftSurvey = getDraftSurveyFromSessionStorage();
selectTemplate(draftSurvey?.title ?? '', draftSurvey?.questions ?? []);
handleRestart();
setPreviewIndex(0);
toggleOnLargeScreen();
};
const [showGallery, setShowGallery] = useState(false);
const [isWarningOpen, setIsWarningOpen] = useState(false);
const [pendingTemplate, setPendingTemplate] = useState<Template | null>(null);

const handleTemplatePreview = (
const handleTemplateClick = (
event: React.MouseEvent<HTMLDivElement>,
template: Template,
previewIndex: number
template: Template
) => {
event.stopPropagation();

selectTemplate(template.title, template.questions);
handleRestart();
setPreviewIndex(previewIndex);
toggleOnLargeScreen();
setPendingTemplate(template);
setIsWarningOpen(true);
};

const handleTemplatePick = (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
setIsTemplatePicked(true);
const confirmTemplateChange = () => {
if (pendingTemplate) {
selectTemplate(pendingTemplate.title, pendingTemplate.questions);
handleRestart();
}
setIsWarningOpen(false);
setShowGallery(false);
setPendingTemplate(null);
};

const isDraftSurvey = !!getDraftSurveyFromSessionStorage();

const fieldsCount = 1 + (isDraftSurvey ? 1 : 0) + TEMPLATES.length;

return (
<>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
{isDraftSurvey && (
<TemplateItem
onTemplatePick={handleTemplatePick}
title="Continue from where you left off"
onTemplatePreview={handleContinueLastSurveyPreview}
isInPreview={previewIndex === 0}
buttonContent="Continue"
/>
)}

<TemplateItem
onTemplatePick={handleTemplatePick}
onTemplatePreview={(e) =>
handleTemplatePreview(e, { title: '', questions: [] }, 1)
}
isInPreview={previewIndex === 1}
buttonContent="Start from scratch"
fieldTestSelector="start-from-scratch-field"
buttonTestSelector="start-from-scratch-button"
/>

{TEMPLATES.map((template, index) => (
<TemplateItem
key={index}
onTemplatePick={handleTemplatePick}
template={template}
title={template.title}
isInPreview={previewIndex === index + 2}
onTemplatePreview={(e) =>
handleTemplatePreview(e, template, index + 2)
}
/>
))}
<div
className={clsx(
'flex h-[140px] flex-grow flex-col items-center justify-center rounded border border-dashed border-zinc-600/50 p-2',
fieldsCount % 2 === 0 ? 'md:col-span-2' : 'md:col-span-1'
)}
>
<div className="mb-2 font-semibold">More templates soon!</div>
<div>
Any suggestions?
<a
target="_blank"
className="ml-1 underline"
href="https://github.com/Ryczko/FormsLab/issues"
>
Create an issue
</a>
<StyledDialog
isOpen={isWarningOpen}
onClose={() => setIsWarningOpen(false)}
title="Warning"
content={
<div className="mt-4 flex flex-col gap-4">
<span>
All unsaved changes will be lost. Are you sure you want to
continue?
</span>
<div className="mt-2 flex justify-between gap-2">
<Button
variant={ButtonVariant.SECONDARY}
onClick={() => setIsWarningOpen(false)}
>
Cancel
</Button>
<Button
variant={ButtonVariant.DANGER}
onClick={confirmTemplateChange}
data-test-id="confirm-template-change"
>
Continue
</Button>
</div>
</div>
</div>
}
/>
<div className="mb-2 flex items-center justify-between md:mb-4">
<span className="text-base font-semibold md:text-lg">
Start a new form
</span>
<button
className="flex items-center gap-2 text-sm"
onClick={() => setShowGallery((prev) => !prev)}
data-test-id={'expand-templates'}
>
Pick template
{showGallery ? (
<ChevronUpIcon className="h-5 w-5" />
) : (
<ChevronDownIcon className="h-5 w-5" />
)}
</button>
</div>
{showGallery && (
<>
<div className="my-4 grid grid-cols-1 gap-2 md:grid-cols-3">
<TemplateItem
onTemplatePreview={(e) =>
handleTemplateClick(e, { title: '', questions: [] })
}
fieldTestSelector="start-from-scratch-field"
/>
{TEMPLATES.map((template, index) => (
<TemplateItem
key={`gallery-${index}`}
title={template.title}
onTemplatePreview={(e) => handleTemplateClick(e, template)}
/>
))}
</div>
<hr className="mb-4" />
</>
)}
</>
);
}
Expand Down
Loading