diff --git a/package-lock.json b/package-lock.json
index ae7cf659..7e16630b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,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",
@@ -5232,6 +5233,11 @@
"color-support": "bin.js"
}
},
+ "node_modules/colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
+ },
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
@@ -17460,6 +17466,11 @@
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
},
+ "colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
+ },
"colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
diff --git a/package.json b/package.json
index ab5fd76f..aa0ac061 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 9dedcb60..fc16d041 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -73,6 +73,7 @@ model Survey {
answers Answer[]
oneQuestionPerStep Boolean
displayTitle Boolean
+ accentColor String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
diff --git a/src/features/surveys/components/SurveyOptionsModal/SurveyOptionsModal.tsx b/src/features/surveys/components/SurveyOptionsModal/SurveyOptionsModal.tsx
index 0a518472..8e129553 100644
--- a/src/features/surveys/components/SurveyOptionsModal/SurveyOptionsModal.tsx
+++ b/src/features/surveys/components/SurveyOptionsModal/SurveyOptionsModal.tsx
@@ -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({
@@ -47,6 +47,21 @@ export default function SurveyOptionsModalModal({
}}
label={t('surveyOptionsModal.DisplayTitle')}
/>
+
+
+
+
Accent color
+
{
+ updateOptions('accentColor', e.target.value);
+ }}
+ title="Choose your color"
+ />
+
}
/>
diff --git a/src/features/surveys/features/SurveyCreator/components/PreviewPanel/PreviewPanel.tsx b/src/features/surveys/features/SurveyCreator/components/PreviewPanel/PreviewPanel.tsx
index 3c4c80ce..ea6b617a 100644
--- a/src/features/surveys/features/SurveyCreator/components/PreviewPanel/PreviewPanel.tsx
+++ b/src/features/surveys/features/SurveyCreator/components/PreviewPanel/PreviewPanel.tsx
@@ -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: '',
diff --git a/src/features/surveys/features/SurveyCreator/managers/createSurveyManager/createSurveyManager.ts b/src/features/surveys/features/SurveyCreator/managers/createSurveyManager/createSurveyManager.ts
index ea7985f2..6cd95eac 100644
--- a/src/features/surveys/features/SurveyCreator/managers/createSurveyManager/createSurveyManager.ts
+++ b/src/features/surveys/features/SurveyCreator/managers/createSurveyManager/createSurveyManager.ts
@@ -23,6 +23,7 @@ export interface Question {
export interface SurveyOptions {
oneQuestionPerStep: boolean;
displayTitle: boolean;
+ accentColor: string;
}
export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
@@ -43,6 +44,7 @@ export const useCreateSurveyManager = (initialData?: SurveyWithQuestions) => {
const [surveyOptions, setSurveyOptions] = useState({
oneQuestionPerStep: initialData?.oneQuestionPerStep ?? true,
displayTitle: initialData?.displayTitle ?? true,
+ accentColor: initialData?.accentColor ?? '#C7D2FE',
});
const [error, setError] = useState('');
@@ -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 }));
};
@@ -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,
@@ -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,
diff --git a/src/features/surveys/features/SurveyDisplay/components/AllQuestionsView/AllQuestionsView.tsx b/src/features/surveys/features/SurveyDisplay/components/AllQuestionsView/AllQuestionsView.tsx
index abe85329..18d688f0 100644
--- a/src/features/surveys/features/SurveyDisplay/components/AllQuestionsView/AllQuestionsView.tsx
+++ b/src/features/surveys/features/SurveyDisplay/components/AllQuestionsView/AllQuestionsView.tsx
@@ -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');
@@ -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')}
diff --git a/src/features/surveys/features/SurveyDisplay/components/AnswersComponent/AnswersComponentFactory.tsx b/src/features/surveys/features/SurveyDisplay/components/AnswersComponent/AnswersComponentFactory.tsx
index e6354812..53241676 100644
--- a/src/features/surveys/features/SurveyDisplay/components/AnswersComponent/AnswersComponentFactory.tsx
+++ b/src/features/surveys/features/SurveyDisplay/components/AnswersComponent/AnswersComponentFactory.tsx
@@ -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;
@@ -63,6 +64,7 @@ export const AnswersComponentFactory = (
sizeType={ButtonSize.FULL}
onClick={handlePreviousQuestion}
disabled={isAnswering}
+ className="text-black"
>
{t('back')}
@@ -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')}
diff --git a/src/features/surveys/features/SurveyDisplay/components/OneQuestionView/OneQuestionView.tsx b/src/features/surveys/features/SurveyDisplay/components/OneQuestionView/OneQuestionView.tsx
index 2584b3de..8b6c7bc5 100644
--- a/src/features/surveys/features/SurveyDisplay/components/OneQuestionView/OneQuestionView.tsx
+++ b/src/features/surveys/features/SurveyDisplay/components/OneQuestionView/OneQuestionView.tsx
@@ -21,6 +21,7 @@ export default function OneQuestionView() {
currentStep={activeQuestionIndex + 1}
totalSteps={formData?.questions.length}
isSubmitted={isAnswering}
+ accentColor={formData?.accentColor}
/>
>
)}
diff --git a/src/features/surveys/features/SurveyDisplay/utils/getFontColor.ts b/src/features/surveys/features/SurveyDisplay/utils/getFontColor.ts
new file mode 100644
index 00000000..15764e38
--- /dev/null
+++ b/src/features/surveys/features/SurveyDisplay/utils/getFontColor.ts
@@ -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';
+};
diff --git a/src/pages/api/survey/[id].ts b/src/pages/api/survey/[id].ts
index 36384ca6..a849a325 100644
--- a/src/pages/api/survey/[id].ts
+++ b/src/pages/api/survey/[id].ts
@@ -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();
@@ -189,6 +190,7 @@ export default async function handler(
description,
oneQuestionPerStep,
displayTitle,
+ accentColor,
},
});
diff --git a/src/pages/api/survey/index.ts b/src/pages/api/survey/index.ts
index 6dd765df..1185e130 100644
--- a/src/pages/api/survey/index.ts
+++ b/src/pages/api/survey/index.ts
@@ -17,6 +17,7 @@ export interface SurveyData {
questions: Question[];
oneQuestionPerStep: boolean;
displayTitle: boolean;
+ accentColor: string;
}
export async function getAllUserSurveys(userId: string) {
@@ -76,6 +77,7 @@ export default async function handler(
questions,
oneQuestionPerStep,
displayTitle,
+ accentColor,
} = req.body as SurveyData;
if (!isSurveyValid(req.body)) {
@@ -87,6 +89,7 @@ export default async function handler(
user: { connect: { id: session.currentUser.id } },
title,
description,
+ accentColor,
isActive: true,
oneQuestionPerStep,
displayTitle,
diff --git a/src/shared/components/Button/Button.tsx b/src/shared/components/Button/Button.tsx
index ae97ffcc..4df62bb2 100644
--- a/src/shared/components/Button/Button.tsx
+++ b/src/shared/components/Button/Button.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { CSSProperties } from 'react';
import clsx from 'clsx';
import Loader from 'shared/components/Loader/Loader';
@@ -25,6 +25,7 @@ export interface ButtonProps {
className?: string | undefined;
type?: 'button' | 'submit' | 'reset' | undefined;
icon?: React.ReactNode;
+ style?: CSSProperties;
}
const Button = ({
@@ -36,6 +37,7 @@ const Button = ({
disabled = false,
type = 'button',
icon,
+ style,
...props
}: ButtonProps & React.HTMLProps) => (