Add option ask for short answers in Open Text questions (#435)

* feat: add shortAnswer: boolean to OpenTextQuestion interface

* feat: add longAnswer switch to OpenTextForm

* toggle textare lines depending on question.shortAnswer

* fix type build error

* move long answer switch to baseline

* adjust spacing between switches

* rename shortAnswer -> longAnswer, change textarea to input field

---------

Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
Moritz Rengert
2023-06-30 12:10:48 +02:00
committed by GitHub
parent 5dc9dfdb3d
commit 888d10434a
7 changed files with 81 additions and 19 deletions

View File

@@ -45,6 +45,7 @@ export const customSurvey: Template = {
headline: "Custom Survey",
subheader: "This is an example survey.",
placeholder: "Type your answer here...",
longAnswer: true,
required: true,
},
],
@@ -116,12 +117,14 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "What type of people do you think would most benefit from Formbricks?",
longAnswer: true,
required: true,
},
{
id: createId(),
type: QuestionType.OpenText,
headline: "What is the main benefit your receive from Formbricks?",
longAnswer: true,
required: true,
},
{
@@ -129,6 +132,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "How can we improve our service for you?",
subheader: "Please be as specific as possible.",
longAnswer: true,
required: true,
},
],
@@ -298,6 +302,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "Would you like to add something?",
subheader: "Feel free to speak your mind, we do too.",
longAnswer: true,
required: false,
},
],
@@ -387,6 +392,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "How can we win you back?",
subheader: "Feel free to speak your mind, we do too.",
longAnswer: true,
required: false,
},
],
@@ -434,6 +440,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "Any details to share?",
longAnswer: true,
required: false,
},
{
@@ -441,6 +448,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "How are you solving your problem instead?",
subheader: "Please name alternative tools:",
longAnswer: true,
required: false,
},
],
@@ -549,6 +557,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "What did you come here to do today?",
longAnswer: true,
required: false,
},
],
@@ -615,6 +624,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "Wanna add something?",
subheader: "This really helps us do better!",
longAnswer: true,
required: false,
},
],
@@ -678,6 +688,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "How can we improve our service for you?",
subheader: "Please be as specific as possible.",
longAnswer: true,
required: true,
},
],
@@ -713,6 +724,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "Give us the juicy details:",
longAnswer: true,
required: true,
},
],
@@ -760,6 +772,7 @@ export const templates: Template[] = [
type: QuestionType.OpenText,
headline: "Which product would you like to integrate next?",
subheader: "We keep building integrations. Yours can be next:",
longAnswer: true,
required: false,
},
],
@@ -806,6 +819,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "If you chose other, please clarify:",
longAnswer: true,
required: false,
},
],
@@ -840,12 +854,14 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "Please elaborate:",
longAnswer: true,
required: false,
},
{
id: createId(),
type: QuestionType.OpenText,
headline: "Page URL",
longAnswer: true,
required: false,
},
],
@@ -974,6 +990,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "What's the #1 thing you'd like to change in Formbricks?",
longAnswer: true,
required: false,
},
],
@@ -1002,6 +1019,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "What is one thing we could do better?",
longAnswer: true,
required: false,
},
],
@@ -1040,6 +1058,7 @@ export const templates: Template[] = [
id: createId(),
type: QuestionType.OpenText,
headline: "Whats missing or unclear to you about Formbricks?",
longAnswer: true,
required: false,
},
{

View File

@@ -227,8 +227,24 @@ export default function QuestionCard({
</Collapsible.CollapsibleContent>
{open && (
<div className="m-4 mt-0 border-t border-slate-200">
<div className="m-4 mr-0 flex items-center justify-end space-x-2">
<div className="mx-4 flex justify-end space-x-6 border-t border-slate-200">
{question.type === "openText" && (
<div className="my-4 flex items-center justify-end space-x-2">
<Label htmlFor="longAnswer">Long Answer</Label>
<Switch
id="longAnswer"
checked={question.longAnswer !== false}
onClick={(e) => {
e.stopPropagation();
updateQuestion(questionIdx, {
longAnswer:
typeof question.longAnswer === "undefined" ? false : !question.longAnswer,
});
}}
/>
</div>
)}
<div className="my-4 flex items-center justify-end space-x-2">
<Label htmlFor="required-toggle">Required</Label>
<Switch
id="required-toggle"

View File

@@ -33,16 +33,30 @@ export default function OpenTextQuestion({
<Headline headline={question.headline} questionId={question.id} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<textarea
autoFocus
rows={3}
name={question.id}
id={question.id}
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder={question.placeholder}
required={question.required}
className="block w-full rounded-md border border-slate-100 bg-slate-50 p-2 shadow-sm focus:border-slate-500 focus:ring-0 sm:text-sm"></textarea>
{question.longAnswer === false ? (
<input
autoFocus
name={question.id}
id={question.id}
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder={question.placeholder}
required={question.required}
className="block w-full rounded-md border border-slate-100 bg-slate-50 p-2 shadow-sm focus:border-slate-500 focus:outline-none focus:ring-0 sm:text-sm"
/>
) : (
<textarea
autoFocus
rows={3}
name={question.id}
id={question.id}
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder={question.placeholder}
required={question.required}
className="block w-full rounded-md border border-slate-100 bg-slate-50 p-2 shadow-sm focus:border-slate-500 focus:ring-0 sm:text-sm"
/>
)}
</div>
<div className="mt-4 flex w-full justify-between">
<div></div>

View File

@@ -29,6 +29,7 @@ export const questionTypes: QuestionType[] = [
headline: "Who let the dogs out?",
subheader: "Who? Who? Who?",
placeholder: "Type your answer here...",
longAnswer: true,
},
},
{

View File

@@ -31,13 +31,23 @@ export default function OpenTextQuestion({
<Headline headline={question.headline} questionId={question.id} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="fb-mt-4">
<textarea
rows={3}
name={question.id}
id={question.id}
placeholder={question.placeholder}
required={question.required}
className="fb-block fb-w-full fb-rounded-md fb-border fb-p-2 fb-shadow-sm focus:fb-ring-0 sm:fb-text-sm fb-bg-slate-50 fb-border-slate-100 focus:fb-border-slate-500"></textarea>
{question.longAnswer === false ? (
<input
name={question.id}
id={question.id}
placeholder={question.placeholder}
required={question.required}
className="fb-block fb-w-full fb-rounded-md fb-border fb-p-2 fb-shadow-sm focus:fb-ring-0 sm:fb-text-sm fb-bg-slate-50 fb-border-slate-100 focus:fb-border-slate-500 focus:fb-outline-none"
/>
) : (
<textarea
rows={3}
name={question.id}
id={question.id}
placeholder={question.placeholder}
required={question.required}
className="fb-block fb-w-full fb-rounded-md fb-border fb-p-2 fb-shadow-sm focus:fb-ring-0 sm:fb-text-sm fb-bg-slate-50 fb-border-slate-100 focus:fb-border-slate-500"></textarea>
)}
</div>
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-between">
<div></div>

View File

@@ -34,6 +34,7 @@ export interface IQuestion<T extends Logic> {
export interface OpenTextQuestion extends IQuestion<OpenTextLogic> {
type: QuestionType.OpenText;
longAnswer?: boolean;
placeholder?: string;
}

View File

@@ -117,6 +117,7 @@ const ZSurveyQuestionBase = z.object({
export const ZSurveyOpenTextQuestion = ZSurveyQuestionBase.extend({
type: z.literal(QuestionType.OpenText),
placeholder: z.string().optional(),
longAnswer: z.boolean().optional(),
logic: z.array(ZSurveyOpenTextLogic).optional(),
});