feat: Mandatory question indicator added

feat: Mandatory question indicator added
This commit is contained in:
Johannes
2023-10-02 13:47:12 +05:45
committed by GitHub
17 changed files with 58 additions and 50 deletions

View File

@@ -1,3 +1,4 @@
import Headline from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/Headline";
import type { QuestionSummary } from "@formbricks/types/responses";
import { TSurveyCTAQuestion } from "@formbricks/types/v1/surveys";
import { ProgressBar } from "@formbricks/ui";
@@ -27,11 +28,8 @@ export default function CTASummary({ questionSummary }: CTASummaryProps) {
return (
<div className=" rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
<div className="space-y-2 px-4 pb-5 pt-6 md:px-6">
<div>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">
{questionSummary.question.headline}
</h3>
</div>
<Headline headline={questionSummary.question.headline} required={questionSummary.question.required} />
<div className="flex space-x-2 text-xs font-semibold text-slate-600 md:text-sm">
<div className="rounded-lg bg-slate-100 p-2 ">Call-to-Action</div>
<div className=" flex items-center rounded-lg bg-slate-100 p-2">

View File

@@ -3,6 +3,7 @@ import { ProgressBar } from "@formbricks/ui";
import { InboxStackIcon } from "@heroicons/react/24/solid";
import { useMemo } from "react";
import { TSurveyConsentQuestion } from "@formbricks/types/v1/surveys";
import Headline from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/Headline";
interface ConsentSummaryProps {
questionSummary: QuestionSummary<TSurveyConsentQuestion>;
@@ -35,11 +36,7 @@ export default function ConsentSummary({ questionSummary }: ConsentSummaryProps)
return (
<div className=" rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
<div className="space-y-2 px-4 pb-5 pt-6 md:px-6">
<div>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">
{questionSummary.question.headline}
</h3>
</div>
<Headline headline={questionSummary.question.headline} required={questionSummary.question.required} />
<div className="flex space-x-2 text-xs font-semibold text-slate-600 md:text-sm">
<div className="rounded-lg bg-slate-100 p-2">Consent</div>
<div className=" flex items-center rounded-lg bg-slate-100 p-2">

View File

@@ -0,0 +1,17 @@
interface HeadlineProps {
headline: string;
required?: boolean;
}
export default function Headline({ headline, required = true }: HeadlineProps) {
return (
<div className={"align-center flex justify-between gap-4 "}>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">{headline}</h3>
{!required && (
<span className="text-md pb-1 font-light leading-7 text-gray-500" tabIndex={-1}>
Optional
</span>
)}
</div>
);
}

View File

@@ -9,6 +9,7 @@ import {
TSurveyMultipleChoiceMultiQuestion,
TSurveyMultipleChoiceSingleQuestion,
} from "@formbricks/types/v1/surveys";
import Headline from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/Headline";
interface MultipleChoiceSummaryProps {
questionSummary: QuestionSummary<TSurveyMultipleChoiceMultiQuestion | TSurveyMultipleChoiceSingleQuestion>;
@@ -125,11 +126,8 @@ export default function MultipleChoiceSummary({
return (
<div className=" rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
<div className="space-y-2 px-4 pb-5 pt-6 md:px-6">
<div>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">
{questionSummary.question.headline}
</h3>
</div>
<Headline headline={questionSummary.question.headline} required={questionSummary.question.required} />
<div className="flex space-x-2 text-xs font-semibold text-slate-600 md:text-sm">
<div className="rounded-lg bg-slate-100 p-2">
{isSingleChoice

View File

@@ -1,3 +1,4 @@
import Headline from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/Headline";
import type { QuestionSummary } from "@formbricks/types/responses";
import { TSurveyNPSQuestion } from "@formbricks/types/v1/surveys";
import { HalfCircle, ProgressBar } from "@formbricks/ui";
@@ -75,11 +76,8 @@ export default function NPSSummary({ questionSummary }: NPSSummaryProps) {
return (
<div className=" rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
<div className="space-y-2 px-4 pb-5 pt-6 md:px-6">
<div>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">
{questionSummary.question.headline}
</h3>
</div>
<Headline headline={questionSummary.question.headline} required={questionSummary.question.required} />
<div className="flex space-x-2 text-xs font-semibold text-slate-600 md:text-sm">
<div className="rounded-lg bg-slate-100 p-2">Net Promoter Score (NPS)</div>
<div className=" flex items-center rounded-lg bg-slate-100 p-2">

View File

@@ -1,3 +1,4 @@
import Headline from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/Headline";
import { truncate } from "@/lib/utils";
import { timeSince } from "@formbricks/lib/time";
import type { QuestionSummary } from "@formbricks/types/responses";
@@ -19,11 +20,8 @@ export default function OpenTextSummary({ questionSummary, environmentId }: Open
return (
<div className="rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
<div className="space-y-2 px-4 pb-5 pt-6 md:px-6">
<div>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">
{questionSummary.question.headline}
</h3>
</div>
<Headline headline={questionSummary.question.headline} required={questionSummary.question.required} />
<div className="flex space-x-2 text-xs font-semibold text-slate-600 md:text-sm">
<div className="rounded-lg bg-slate-100 p-2 ">Open Text Question</div>
<div className=" flex items-center rounded-lg bg-slate-100 p-2">

View File

@@ -5,6 +5,7 @@ import { useMemo } from "react";
import { QuestionType } from "@formbricks/types/questions";
import { TSurveyRatingQuestion } from "@formbricks/types/v1/surveys";
import { RatingResponse } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/RatingResponse";
import Headline from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/Headline";
interface RatingSummaryProps {
questionSummary: QuestionSummary<TSurveyRatingQuestion>;
@@ -77,11 +78,8 @@ export default function RatingSummary({ questionSummary }: RatingSummaryProps) {
return (
<div className=" rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
<div className="space-y-2 px-4 pb-5 pt-6 md:px-6">
<div>
<h3 className="pb-1 text-lg font-semibold text-slate-900 md:text-xl">
{questionSummary.question.headline}
</h3>
</div>
<Headline headline={questionSummary.question.headline} required={questionSummary.question.required} />
<div className="flex space-x-2 text-xs font-semibold text-slate-600 md:text-sm">
<div className="rounded-lg bg-slate-100 p-2">Rating Question</div>
<div className="flex items-center rounded-lg bg-slate-100 p-2">

View File

@@ -1,10 +1,12 @@
"use client";
import React from "react";
import AlertDialog from "@/components/shared/AlertDialog";
import DeleteDialog from "@/components/shared/DeleteDialog";
import SurveyStatusDropdown from "@/components/shared/SurveyStatusDropdown";
import type { Survey } from "@formbricks/types/surveys";
import { TEnvironment } from "@formbricks/types/v1/environment";
import { TProduct } from "@formbricks/types/v1/product";
import { TSurvey, TSurveyWithAnalytics } from "@formbricks/types/v1/surveys";
import { Button, Input } from "@formbricks/ui";
import { ArrowLeftIcon, Cog8ToothIcon, ExclamationTriangleIcon } from "@heroicons/react/24/solid";
import { isEqual } from "lodash";
@@ -12,10 +14,7 @@ import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import { validateQuestion } from "./Validation";
import { TSurvey, TSurveyWithAnalytics } from "@formbricks/types/v1/surveys";
import { deleteSurveyAction, surveyMutateAction } from "./actions";
import { TProduct } from "@formbricks/types/v1/product";
import { TEnvironment } from "@formbricks/types/v1/environment";
interface SurveyMenuBarProps {
localSurvey: TSurveyWithAnalytics;
@@ -197,8 +196,8 @@ export default function SurveyMenuBar({
{!!localSurvey.analytics.responseRate && (
<div className="mx-auto flex items-center rounded-full border border-amber-200 bg-amber-100 p-2 text-amber-700 shadow-sm">
<ExclamationTriangleIcon className=" h-5 w-5 text-amber-400" />
<p className="max-w-[90%] pl-1 text-xs lg:text-sm">
This survey received responses. To keep the data consistent, make changes with caution.
<p className=" pl-1 text-xs lg:text-sm">
This survey received responses, make changes with caution.
</p>
</div>
)}

View File

@@ -26,7 +26,7 @@ export default function CTAQuestion({
}: CTAQuestionProps) {
return (
<div>
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<HtmlBody htmlString={question.html} questionId={question.id} />
<div className="mt-4 flex w-full justify-between">

View File

@@ -28,7 +28,7 @@ export default function ConsentQuestion({
}: ConsentQuestionProps) {
return (
<div>
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<HtmlBody htmlString={question.html || ""} questionId={question.id} />
<form

View File

@@ -2,15 +2,20 @@ interface HeadlineProps {
headline?: string;
questionId: string;
style?: any;
required?: boolean;
}
export default function Headline({ headline, questionId, style }: HeadlineProps) {
export default function Headline({ headline, questionId, style, required = true }: HeadlineProps) {
return (
<label
htmlFor={questionId}
className="mb-1.5 mr-8 block text-base font-semibold leading-6 text-slate-900"
style={style}>
{headline}
<label htmlFor={questionId} className="mb-1.5 block text-base font-semibold leading-6 text-slate-900">
<div className={"flex justify-between gap-4"} style={style}>
{headline}
{!required && (
<span className="self-start text-sm font-normal leading-7 text-slate-400" tabIndex={-1}>
Optional
</span>
)}
</div>
</label>
);
}

View File

@@ -83,7 +83,7 @@ export default function MultipleChoiceSingleQuestion({
onSubmit({ [question.id]: value });
}}
className="w-full">
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<fieldset>

View File

@@ -63,7 +63,7 @@ export default function MultipleChoiceSingleQuestion({
onSubmit({ [question.id]: value });
}}
className="w-full">
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<fieldset>

View File

@@ -33,7 +33,7 @@ export default function NPSQuestion({
e.preventDefault();
onSubmit({ [question.id]: value });
}}>
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="my-4">
<fieldset>

View File

@@ -35,7 +35,7 @@ export default function OpenTextQuestion({
onSubmit({ [question.id]: value });
}}
className="w-full">
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
{question.longAnswer === false ? (

View File

@@ -70,7 +70,7 @@ export default function RatingQuestion({
onSubmit({ [question.id]: value });
}}
className="w-full">
<Headline headline={question.headline} questionId={question.id} />
<Headline headline={question.headline} questionId={question.id} required={question.required} />
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="my-4">
<fieldset>

View File

@@ -38,7 +38,7 @@ export default function ThankYouCard({
<span className="mb-[10px] inline-block h-1 w-16 rounded-[100%] bg-slate-300"></span>
<div>
<Headline headline={headline} questionId="thankYouCard" style={{ "margin-right": 0 }} />
<Headline headline={headline} questionId="thankYouCard" style={{ "justify-content": "center" }} />
<Subheader subheader={subheader} questionId="thankYouCard" />
<RedirectCountDown redirectUrl={redirectUrl} isRedirectDisabled={isRedirectDisabled} />
</div>