mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-23 10:09:20 -06:00
fix: inconsistencies in survey summary (#4032)
Co-authored-by: Johannes <johannes@formbricks.com>
This commit is contained in:
@@ -61,7 +61,7 @@ export const SurveyMenuBar = ({
|
||||
const [isConfirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
||||
const [isSurveyPublishing, setIsSurveyPublishing] = useState(false);
|
||||
const [isSurveySaving, setIsSurveySaving] = useState(false);
|
||||
const cautionText = "This survey received responses.";
|
||||
const cautionText = "Changes will lead to inconsistencies.";
|
||||
|
||||
useEffect(() => {
|
||||
if (audiencePrompt && activeId === "settings") {
|
||||
|
||||
@@ -44,7 +44,7 @@ export const CTASummary = ({ questionSummary, survey, attributeClasses }: CTASum
|
||||
<p className="font-semibold text-slate-700">CTR</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(questionSummary.ctr.percentage, 1)}%
|
||||
{convertFloatToNDecimal(questionSummary.ctr.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,7 +26,7 @@ export const CalSummary = ({ questionSummary, survey, attributeClasses }: CalSum
|
||||
<p className="font-semibold text-slate-700">Booked</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(questionSummary.booked.percentage, 1)}%
|
||||
{convertFloatToNDecimal(questionSummary.booked.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -42,7 +42,7 @@ export const CalSummary = ({ questionSummary, survey, attributeClasses }: CalSum
|
||||
<p className="font-semibold text-slate-700">Dismissed</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(questionSummary.skipped.percentage, 1)}%
|
||||
{convertFloatToNDecimal(questionSummary.skipped.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,7 +70,7 @@ export const ConsentSummary = ({
|
||||
</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(summaryItem.percentage, 1)}%
|
||||
{convertFloatToNDecimal(summaryItem.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@ export const MultipleChoiceSummary = ({
|
||||
questionSummary.type === "multipleChoiceMulti" ? (
|
||||
<div className="flex items-center rounded-lg bg-slate-100 p-2">
|
||||
<InboxIcon className="mr-2 h-4 w-4" />
|
||||
{`${questionSummary.selectionCount} selections`}
|
||||
{`${questionSummary.selectionCount} Selections`}
|
||||
</div>
|
||||
) : undefined
|
||||
}
|
||||
@@ -101,12 +101,12 @@ export const MultipleChoiceSummary = ({
|
||||
</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(result.percentage, 1)}%
|
||||
{convertFloatToNDecimal(result.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="flex w-full pt-1 text-slate-600 sm:items-end sm:justify-end sm:pt-0">
|
||||
{result.count} {result.count === 1 ? "selection" : "selections"}
|
||||
{result.count} {result.count === 1 ? "Selection" : "Selections"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="group-hover:opacity-80">
|
||||
|
||||
@@ -76,7 +76,7 @@ export const NPSSummary = ({ questionSummary, survey, attributeClasses, setFilte
|
||||
</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(questionSummary[group]?.percentage, 1)}%
|
||||
{convertFloatToNDecimal(questionSummary[group]?.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -102,7 +102,7 @@ export const OpenTextSummary = ({
|
||||
<TableBody>
|
||||
{questionSummary.samples.slice(0, visibleResponses).map((response) => (
|
||||
<TableRow key={response.id}>
|
||||
<TableCell>
|
||||
<TableCell width={180}>
|
||||
{response.person ? (
|
||||
<Link
|
||||
className="ph-no-capture group flex items-center"
|
||||
@@ -110,7 +110,7 @@ export const OpenTextSummary = ({
|
||||
<div className="hidden md:flex">
|
||||
<PersonAvatar personId={response.person.id} />
|
||||
</div>
|
||||
<p className="ph-no-capture break-all text-slate-600 group-hover:underline md:ml-2">
|
||||
<p className="ph-no-capture break-normal text-slate-600 group-hover:underline md:ml-2">
|
||||
{getPersonIdentifier(response.person, response.personAttributes)}
|
||||
</p>
|
||||
</Link>
|
||||
@@ -119,12 +119,12 @@ export const OpenTextSummary = ({
|
||||
<div className="hidden md:flex">
|
||||
<PersonAvatar personId="anonymous" />
|
||||
</div>
|
||||
<p className="break-all text-slate-600 md:ml-2">Anonymous</p>
|
||||
<p className="break-normal text-slate-600 md:ml-2">Anonymous</p>
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">{response.value}</TableCell>
|
||||
<TableCell>{timeSince(new Date(response.updatedAt).toISOString())}</TableCell>
|
||||
<TableCell width={120}>{timeSince(new Date(response.updatedAt).toISOString())}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { InboxIcon } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { TAttributeClass } from "@formbricks/types/attribute-classes";
|
||||
import {
|
||||
@@ -38,6 +39,14 @@ export const PictureChoiceSummary = ({
|
||||
questionSummary={questionSummary}
|
||||
survey={survey}
|
||||
attributeClasses={attributeClasses}
|
||||
additionalInfo={
|
||||
questionSummary.question.allowMulti ? (
|
||||
<div className="flex items-center rounded-lg bg-slate-100 p-2">
|
||||
<InboxIcon className="mr-2 h-4 w-4" />
|
||||
{`${questionSummary.selectionCount} Selections`}
|
||||
</div>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
<div className="space-y-5 px-4 pb-6 pt-4 text-sm md:px-6 md:text-base">
|
||||
{results.map((result, index) => (
|
||||
@@ -66,12 +75,12 @@ export const PictureChoiceSummary = ({
|
||||
</div>
|
||||
<div className="self-end">
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(result.percentage, 1)}%
|
||||
{convertFloatToNDecimal(result.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="flex w-full pt-1 text-slate-600 sm:items-end sm:justify-end sm:pt-0">
|
||||
{result.count} {result.count === 1 ? "response" : "responses"}
|
||||
{result.count} {result.count === 1 ? "Selection" : "Selections"}
|
||||
</p>
|
||||
</div>
|
||||
<ProgressBar barColor="bg-brand-dark" progress={result.percentage / 100 || 0} />
|
||||
|
||||
@@ -38,7 +38,7 @@ export const RankingSummary = ({
|
||||
<div className="rounded bg-gray-100 px-2 py-1">{result.value}</div>
|
||||
<span className="ml-auto flex items-center space-x-1">
|
||||
<span className="font-bold text-slate-600">
|
||||
#{convertFloatToNDecimal(result.avgRanking, 1)}
|
||||
#{convertFloatToNDecimal(result.avgRanking, 2)}
|
||||
</span>
|
||||
<span>average</span>
|
||||
</span>
|
||||
|
||||
@@ -78,7 +78,7 @@ export const RatingSummary = ({
|
||||
</div>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{convertFloatToNDecimal(result.percentage, 1)}%
|
||||
{convertFloatToNDecimal(result.percentage, 2)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -428,12 +428,14 @@ export const getQuestionSummary = async (
|
||||
choiceCountMap[choice.id] = 0;
|
||||
});
|
||||
let totalResponseCount = 0;
|
||||
let totalSelectionCount = 0;
|
||||
|
||||
responses.forEach((response) => {
|
||||
const answer = response.data[question.id];
|
||||
if (Array.isArray(answer)) {
|
||||
totalResponseCount++;
|
||||
answer.forEach((value) => {
|
||||
totalResponseCount++;
|
||||
totalSelectionCount++;
|
||||
choiceCountMap[value]++;
|
||||
});
|
||||
}
|
||||
@@ -445,8 +447,8 @@ export const getQuestionSummary = async (
|
||||
imageUrl: choice.imageUrl,
|
||||
count: choiceCountMap[choice.id],
|
||||
percentage:
|
||||
totalResponseCount > 0
|
||||
? convertFloatTo2Decimal((choiceCountMap[choice.id] / totalResponseCount) * 100)
|
||||
totalSelectionCount > 0
|
||||
? convertFloatTo2Decimal((choiceCountMap[choice.id] / totalSelectionCount) * 100)
|
||||
: 0,
|
||||
});
|
||||
});
|
||||
@@ -455,6 +457,7 @@ export const getQuestionSummary = async (
|
||||
type: question.type,
|
||||
question,
|
||||
responseCount: totalResponseCount,
|
||||
selectionCount: totalSelectionCount,
|
||||
choices: values,
|
||||
});
|
||||
|
||||
|
||||
@@ -2136,6 +2136,7 @@ export const ZSurveyQuestionSummaryPictureSelection = z.object({
|
||||
type: z.literal("pictureSelection"),
|
||||
question: ZSurveyPictureSelectionQuestion,
|
||||
responseCount: z.number(),
|
||||
selectionCount: z.number(),
|
||||
choices: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
|
||||
Reference in New Issue
Block a user