Skip to content

Commit

Permalink
Feature/Survey accent color picker
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryczko authored Jan 27, 2024
1 parent a7d67f0 commit e0a9338
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 7 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"axios": "^1.6.0",
"bcrypt": "^5.1.0",
"clsx": "^1.1.1",
"colord": "^2.9.3",
"date-fns": "^2.28.0",
"emoji-mart": "^5.5.2",
"formik": "^2.2.9",
Expand Down
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ model Survey {
answers Answer[]
oneQuestionPerStep Boolean
displayTitle Boolean
accentColor String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type SurveyOptionsModalProps = {
isOpened: boolean;
closeModal: () => void;
surveyOptions: SurveyOptions;
updateOptions: (option: keyof SurveyOptions, value: boolean) => void;
updateOptions: (option: keyof SurveyOptions, value: boolean | string) => void;
};

export default function SurveyOptionsModalModal({
Expand Down Expand Up @@ -47,6 +47,21 @@ export default function SurveyOptionsModalModal({
}}
label={t('surveyOptionsModal.DisplayTitle')}
/>

<hr className="my-4" />
<div className="flex items-center gap-3 text-sm">
<div>Accent color</div>
<input
type="color"
className="block h-8 w-10 cursor-pointer rounded-md border border-gray-200 bg-white p-0.5 disabled:pointer-events-none disabled:opacity-50 dark:border-gray-700 dark:bg-slate-900"
id="hs-color-input"
value={surveyOptions.accentColor}
onChange={(e) => {
updateOptions('accentColor', e.target.value);
}}
title="Choose your color"
/>
</div>
</div>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default function PreviewPanel() {
oneQuestionPerStep: surveyOptions.oneQuestionPerStep,
userId: '',
title,
accentColor: surveyOptions.accentColor,
createdAt: new Date(),
questions: questions.map((question, index) => ({
surveyId: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface Question {
export interface SurveyOptions {
oneQuestionPerStep: boolean;
displayTitle: boolean;
accentColor: string;
}

export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
Expand All @@ -43,6 +44,7 @@ export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
const [surveyOptions, setSurveyOptions] = useState<SurveyOptions>({
oneQuestionPerStep: initialData?.oneQuestionPerStep ?? true,
displayTitle: initialData?.displayTitle ?? true,
accentColor: initialData?.accentColor ?? '#C7D2FE',
});

const [error, setError] = useState('');
Expand Down Expand Up @@ -76,7 +78,10 @@ export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
sessionStorage.removeItem(DRAFT_SURVEY_SESSION_STORAGE);
}, []);

const updateSurveyOptions = (option: keyof SurveyOptions, value: boolean) => {
const updateSurveyOptions = (
option: keyof SurveyOptions,
value: boolean | string
) => {
setSurveyOptions((oldOptions) => ({ ...oldOptions, [option]: value }));
};

Expand Down Expand Up @@ -240,6 +245,7 @@ export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
title,
oneQuestionPerStep: surveyOptions.oneQuestionPerStep,
displayTitle: surveyOptions.displayTitle,
accentColor: surveyOptions.accentColor,
questions: questions.map((question) => ({
title: question.title,
options: question.options,
Expand Down Expand Up @@ -275,6 +281,7 @@ export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
title,
oneQuestionPerStep: surveyOptions.oneQuestionPerStep,
displayTitle: surveyOptions.displayTitle,
accentColor: surveyOptions.accentColor,
questions: questions.map((question) => ({
id: question.id,
title: question.title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Button, {
import useTranslation from 'next-translate/useTranslation';
import { AnswersComponentFactory } from 'features/surveys/features/SurveyDisplay/components/AnswersComponent/AnswersComponentFactory';
import { useSurveyDisplayContext } from 'features/surveys/features/SurveyDisplay/context';
import { getFontColor } from 'features/surveys/features/SurveyDisplay/utils/getFontColor';

export default function AllQuestionView() {
const { t } = useTranslation('survey');
Expand All @@ -32,6 +33,10 @@ export default function AllQuestionView() {
variant={ButtonVariant.PRIMARY}
sizeType={ButtonSize.FULL}
isLoading={isAnswering}
style={{
backgroundColor: formData.accentColor ?? undefined,
color: getFontColor(formData?.accentColor),
}}
>
{t('sendButton')}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ListAnswersComponent from 'features/surveys/features/SurveyDisplay/compon
import RateAnswersComponent from 'features/surveys/features/SurveyDisplay/components/AnswersComponent/RateComponent/RateComponent';
import TextAnswersComponent from 'features/surveys/features/SurveyDisplay/components/AnswersComponent/TextAnswersComponent';
import { useSurveyDisplayContext } from 'features/surveys/features/SurveyDisplay/context';
import { getFontColor } from 'features/surveys/features/SurveyDisplay/utils/getFontColor';

interface AnswersComponentFactoryProps {
questionIndex: number;
Expand Down Expand Up @@ -63,6 +64,7 @@ export const AnswersComponentFactory = (
sizeType={ButtonSize.FULL}
onClick={handlePreviousQuestion}
disabled={isAnswering}
className="text-black"
>
{t('back')}
</Button>
Expand All @@ -74,6 +76,10 @@ export const AnswersComponentFactory = (
sizeType={ButtonSize.FULL}
onClick={handleNextQuestion}
isLoading={isAnswering}
style={{
backgroundColor: formData.accentColor ?? undefined,
color: getFontColor(formData.accentColor),
}}
>
{isLastQuestion ? t('sendButton') : t('next')}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function OneQuestionView() {
currentStep={activeQuestionIndex + 1}
totalSteps={formData?.questions.length}
isSubmitted={isAnswering}
accentColor={formData?.accentColor}
/>
</>
)}
Expand Down
10 changes: 10 additions & 0 deletions src/features/surveys/features/SurveyDisplay/utils/getFontColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const getFontColor = (color?: string | null) => {
if (!color) return '#000000';

const hex = color.replace('#', '');
const r = parseInt(hex.substr(0, 2), 16);
const g = parseInt(hex.substr(2, 2), 16);
const b = parseInt(hex.substr(4, 2), 16);

return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#ffffff';
};
2 changes: 2 additions & 0 deletions src/pages/api/survey/[id].ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export default async function handler(
questions,
oneQuestionPerStep,
displayTitle,
accentColor,
} = req.body as SurveyData;
if (!isSurveyValid(req.body)) {
return res.status(400).end();
Expand Down Expand Up @@ -189,6 +190,7 @@ export default async function handler(
description,
oneQuestionPerStep,
displayTitle,
accentColor,
},
});

Expand Down
3 changes: 3 additions & 0 deletions src/pages/api/survey/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface SurveyData {
questions: Question[];
oneQuestionPerStep: boolean;
displayTitle: boolean;
accentColor: string;
}

export async function getAllUserSurveys(userId: string) {
Expand Down Expand Up @@ -76,6 +77,7 @@ export default async function handler(
questions,
oneQuestionPerStep,
displayTitle,
accentColor,
} = req.body as SurveyData;

if (!isSurveyValid(req.body)) {
Expand All @@ -87,6 +89,7 @@ export default async function handler(
user: { connect: { id: session.currentUser.id } },
title,
description,
accentColor,
isActive: true,
oneQuestionPerStep,
displayTitle,
Expand Down
5 changes: 4 additions & 1 deletion src/shared/components/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { CSSProperties } from 'react';
import clsx from 'clsx';
import Loader from 'shared/components/Loader/Loader';

Expand All @@ -25,6 +25,7 @@ export interface ButtonProps {
className?: string | undefined;
type?: 'button' | 'submit' | 'reset' | undefined;
icon?: React.ReactNode;
style?: CSSProperties;
}

const Button = ({
Expand All @@ -36,6 +37,7 @@ const Button = ({
disabled = false,
type = 'button',
icon,
style,
...props
}: ButtonProps & React.HTMLProps<HTMLButtonElement>) => (
<button
Expand All @@ -45,6 +47,7 @@ const Button = ({
sizeType,
className
)}
style={style}
disabled={disabled || isLoading}
type={type}
{...props}
Expand Down
31 changes: 27 additions & 4 deletions src/shared/components/ProgressBar/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,56 @@
import { colord, extend } from 'colord';
import mixPlugin from 'colord/plugins/mix';

interface ProgressbarProps {
currentStep: number;
totalSteps: number;
isSubmitted?: boolean;
accentColor?: string | null;
}

export default function Progressbar({
currentStep,
totalSteps,
isSubmitted,
accentColor,
}: ProgressbarProps) {
const percentage =
((currentStep - 1 + (isSubmitted ? 1 : 0)) / totalSteps) * 100;

const getBackgroundColor = () => {
if (!accentColor) return undefined;

extend([mixPlugin]);

const color = colord(accentColor);
const newc = color.tints(3).map((c) => c.toHex());

return newc[1];
};

return (
<div className="relative mt-4 h-[24px] w-full overflow-hidden rounded-lg bg-indigo-100">
<div
className="relative mt-4 h-[12px] w-full overflow-hidden rounded-lg bg-indigo-100"
style={{ background: getBackgroundColor() }}
>
<div
data-testid="progressbar"
style={{ width: `${percentage}%` }}
style={{
width: `${percentage}%`,
backgroundColor: accentColor ?? undefined,
}}
className="h-full bg-indigo-300 transition-all duration-300"
></div>
<span className="text-purple absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-xs font-semibold">

{/* <span className="text-purple absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-xs font-semibold">
{isSubmitted ? (
<span>Submitting...</span>
) : (
<span>
{currentStep - 1} of {totalSteps} completed
</span>
)}
</span>
</span> */}
</div>
);
}

0 comments on commit e0a9338

Please sign in to comment.