mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-22 10:08:42 -06:00
feat: Mandatory question indicator added
feat: Mandatory question indicator added
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ? (
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user