mirror of
https://github.com/formbricks/formbricks.git
synced 2026-02-13 03:10:30 -06:00
feat: No responses due to filter state (#2283)
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
@@ -36,6 +36,7 @@ interface ResponsePageProps {
|
||||
attributes: TSurveyPersonAttributes;
|
||||
responsesPerPage: number;
|
||||
membershipRole?: TMembershipRole;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
const ResponsePage = ({
|
||||
@@ -49,11 +50,13 @@ const ResponsePage = ({
|
||||
attributes,
|
||||
responsesPerPage,
|
||||
membershipRole,
|
||||
totalResponseCount,
|
||||
}: ResponsePageProps) => {
|
||||
const [responseCount, setResponseCount] = useState<number | null>(null);
|
||||
const [responses, setResponses] = useState<TResponse[]>([]);
|
||||
const [page, setPage] = useState<number>(1);
|
||||
const [hasMore, setHasMore] = useState<boolean>(true);
|
||||
const [isFetchingFirstPage, setFetchingFirstPage] = useState<boolean>(true);
|
||||
|
||||
const { selectedFilter, dateRange, resetState } = useResponseFilter();
|
||||
|
||||
@@ -95,17 +98,6 @@ const ResponsePage = ({
|
||||
}
|
||||
}, [searchParams, resetState]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchInitialResponses = async () => {
|
||||
const responses = await getResponsesAction(surveyId, 1, responsesPerPage, filters);
|
||||
if (responses.length < responsesPerPage) {
|
||||
setHasMore(false);
|
||||
}
|
||||
setResponses(responses);
|
||||
};
|
||||
fetchInitialResponses();
|
||||
}, [surveyId, filters, responsesPerPage]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResponsesCount = async () => {
|
||||
const responseCount = await getResponseCountAction(surveyId, filters);
|
||||
@@ -114,6 +106,22 @@ const ResponsePage = ({
|
||||
handleResponsesCount();
|
||||
}, [filters, surveyId]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchInitialResponses = async () => {
|
||||
try {
|
||||
setFetchingFirstPage(true);
|
||||
const responses = await getResponsesAction(surveyId, 1, responsesPerPage, filters);
|
||||
if (responses.length < responsesPerPage) {
|
||||
setHasMore(false);
|
||||
}
|
||||
setResponses(responses);
|
||||
} finally {
|
||||
setFetchingFirstPage(false);
|
||||
}
|
||||
};
|
||||
fetchInitialResponses();
|
||||
}, [surveyId, filters, responsesPerPage]);
|
||||
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
setHasMore(true);
|
||||
@@ -152,6 +160,9 @@ const ResponsePage = ({
|
||||
hasMore={hasMore}
|
||||
deleteResponse={deleteResponse}
|
||||
updateResponse={updateResponse}
|
||||
isFetchingFirstPage={isFetchingFirstPage}
|
||||
responseCount={responseCount}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</ContentWrapper>
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { TTag } from "@formbricks/types/tags";
|
||||
import { TUser } from "@formbricks/types/user";
|
||||
import EmptySpaceFiller from "@formbricks/ui/EmptySpaceFiller";
|
||||
import SingleResponseCard from "@formbricks/ui/SingleResponseCard";
|
||||
import { SkeletonLoader } from "@formbricks/ui/SkeletonLoader";
|
||||
|
||||
interface ResponseTimelineProps {
|
||||
environment: TEnvironment;
|
||||
@@ -24,6 +25,9 @@ interface ResponseTimelineProps {
|
||||
hasMore: boolean;
|
||||
updateResponse: (responseId: string, responses: TResponse) => void;
|
||||
deleteResponse: (responseId: string) => void;
|
||||
isFetchingFirstPage: boolean;
|
||||
responseCount: number | null;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
export default function ResponseTimeline({
|
||||
@@ -36,6 +40,9 @@ export default function ResponseTimeline({
|
||||
hasMore,
|
||||
updateResponse,
|
||||
deleteResponse,
|
||||
isFetchingFirstPage,
|
||||
responseCount,
|
||||
totalResponseCount,
|
||||
}: ResponseTimelineProps) {
|
||||
const loadingRef = useRef(null);
|
||||
|
||||
@@ -69,11 +76,14 @@ export default function ResponseTimeline({
|
||||
<div className="space-y-4">
|
||||
{survey.type === "web" && responses.length === 0 && !environment.widgetSetupCompleted ? (
|
||||
<EmptyInAppSurveys environment={environment} />
|
||||
) : responses.length === 0 ? (
|
||||
) : isFetchingFirstPage ? (
|
||||
<SkeletonLoader type="response" />
|
||||
) : responseCount === 0 ? (
|
||||
<EmptySpaceFiller
|
||||
type="response"
|
||||
environment={environment}
|
||||
noWidgetRequired={survey.type === "link"}
|
||||
emptyMessage={totalResponseCount === 0 ? undefined : "No response matches your filter"}
|
||||
/>
|
||||
) : (
|
||||
<div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { RESPONSES_PER_PAGE, WEBAPP_URL } from "@formbricks/lib/constants";
|
||||
import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getMembershipByUserIdTeamId } from "@formbricks/lib/membership/service";
|
||||
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
|
||||
import { getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getResponseCountBySurveyId, getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getSurvey } from "@formbricks/lib/survey/service";
|
||||
import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service";
|
||||
import { getTeamByEnvironmentId } from "@formbricks/lib/team/service";
|
||||
@@ -47,6 +47,8 @@ export default async function Page({ params }) {
|
||||
|
||||
const currentUserMembership = await getMembershipByUserIdTeamId(session?.user.id, team.id);
|
||||
|
||||
const totalResponseCount = await getResponseCountBySurveyId(params.surveyId);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ResponsePage
|
||||
@@ -60,6 +62,7 @@ export default async function Page({ params }) {
|
||||
user={user}
|
||||
responsesPerPage={RESPONSES_PER_PAGE}
|
||||
membershipRole={currentUserMembership?.role}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { TSurveySummary } from "@formbricks/types/responses";
|
||||
import { TSurveyQuestionType } from "@formbricks/types/surveys";
|
||||
import { TSurvey } from "@formbricks/types/surveys";
|
||||
import EmptySpaceFiller from "@formbricks/ui/EmptySpaceFiller";
|
||||
import { SkeletonLoader } from "@formbricks/ui/SkeletonLoader";
|
||||
|
||||
import CTASummary from "./CTASummary";
|
||||
import DateQuestionSummary from "./DateQuestionSummary";
|
||||
@@ -23,21 +24,31 @@ interface SummaryListProps {
|
||||
responseCount: number | null;
|
||||
environment: TEnvironment;
|
||||
survey: TSurvey;
|
||||
fetchingSummary: boolean;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
export default function SummaryList({ summary, environment, responseCount, survey }: SummaryListProps) {
|
||||
export default function SummaryList({
|
||||
summary,
|
||||
environment,
|
||||
responseCount,
|
||||
survey,
|
||||
fetchingSummary,
|
||||
totalResponseCount,
|
||||
}: SummaryListProps) {
|
||||
return (
|
||||
<div className="mt-10 space-y-8">
|
||||
{survey.type === "web" && responseCount === 0 && !environment.widgetSetupCompleted ? (
|
||||
<EmptyInAppSurveys environment={environment} />
|
||||
) : !responseCount ? (
|
||||
) : fetchingSummary ? (
|
||||
<SkeletonLoader type="summary" />
|
||||
) : responseCount === 0 ? (
|
||||
<EmptySpaceFiller
|
||||
type="response"
|
||||
environment={environment}
|
||||
noWidgetRequired={survey.type === "link"}
|
||||
emptyMessage={totalResponseCount === 0 ? undefined : "No response matches your filter"}
|
||||
/>
|
||||
) : !summary.length ? (
|
||||
<EmptySpaceFiller type="summary" environment={environment} />
|
||||
) : (
|
||||
summary.map((questionSummary) => {
|
||||
if (questionSummary.type === TSurveyQuestionType.OpenText) {
|
||||
|
||||
@@ -52,6 +52,7 @@ interface SummaryPageProps {
|
||||
environmentTags: TTag[];
|
||||
attributes: TSurveyPersonAttributes;
|
||||
membershipRole?: TMembershipRole;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
const SummaryPage = ({
|
||||
@@ -64,11 +65,13 @@ const SummaryPage = ({
|
||||
environmentTags,
|
||||
attributes,
|
||||
membershipRole,
|
||||
totalResponseCount,
|
||||
}: SummaryPageProps) => {
|
||||
const [responseCount, setResponseCount] = useState<number | null>(null);
|
||||
const { selectedFilter, dateRange, resetState } = useResponseFilter();
|
||||
const [surveySummary, setSurveySummary] = useState<TSurveySummary>(initialSurveySummary);
|
||||
const [showDropOffs, setShowDropOffs] = useState<boolean>(false);
|
||||
const [isFetchingSummary, setFetchingSummary] = useState<boolean>(true);
|
||||
|
||||
const filters = useMemo(
|
||||
() => getFormattedFilters(survey, selectedFilter, dateRange),
|
||||
@@ -77,14 +80,19 @@ const SummaryPage = ({
|
||||
|
||||
useEffect(() => {
|
||||
const handleInitialData = async () => {
|
||||
const responseCount = await getResponseCountAction(surveyId, filters);
|
||||
setResponseCount(responseCount);
|
||||
if (responseCount === 0) {
|
||||
setSurveySummary(initialSurveySummary);
|
||||
return;
|
||||
try {
|
||||
setFetchingSummary(true);
|
||||
const responseCount = await getResponseCountAction(surveyId, filters);
|
||||
setResponseCount(responseCount);
|
||||
if (responseCount === 0) {
|
||||
setSurveySummary(initialSurveySummary);
|
||||
return;
|
||||
}
|
||||
const response = await getSurveySummaryAction(surveyId, filters);
|
||||
setSurveySummary(response);
|
||||
} finally {
|
||||
setFetchingSummary(false);
|
||||
}
|
||||
const response = await getSurveySummaryAction(surveyId, filters);
|
||||
setSurveySummary(response);
|
||||
};
|
||||
|
||||
handleInitialData();
|
||||
@@ -135,6 +143,8 @@ const SummaryPage = ({
|
||||
responseCount={responseCount}
|
||||
survey={survey}
|
||||
environment={environment}
|
||||
fetchingSummary={isFetchingSummary}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</ContentWrapper>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { WEBAPP_URL } from "@formbricks/lib/constants";
|
||||
import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getMembershipByUserIdTeamId } from "@formbricks/lib/membership/service";
|
||||
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
|
||||
import { getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getResponseCountBySurveyId, getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getSurvey } from "@formbricks/lib/survey/service";
|
||||
import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service";
|
||||
import { getTeamByEnvironmentId } from "@formbricks/lib/team/service";
|
||||
@@ -55,6 +55,7 @@ export default async function Page({ params }) {
|
||||
|
||||
const tags = await getTagsByEnvironmentId(params.environmentId);
|
||||
const attributes = await getResponsePersonAttributes(params.surveyId);
|
||||
const totalResponseCount = await getResponseCountBySurveyId(params.surveyId);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -68,6 +69,7 @@ export default async function Page({ params }) {
|
||||
environmentTags={tags}
|
||||
attributes={attributes}
|
||||
membershipRole={currentUserMembership?.role}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -53,7 +53,12 @@ const QuestionFilterComboBox = ({
|
||||
|
||||
// when question type is multi selection so we remove the option from the options which has been already selected
|
||||
const options = isMultiple
|
||||
? filterComboBoxOptions?.filter((o) => !filterComboBoxValue?.includes(o))
|
||||
? filterComboBoxOptions?.filter(
|
||||
(o) =>
|
||||
!filterComboBoxValue?.includes(
|
||||
typeof o === "object" ? getLocalizedValue(o, defaultLanguageCode) : o
|
||||
)
|
||||
)
|
||||
: filterComboBoxOptions;
|
||||
|
||||
// disable the combo box for selection of value when question type is nps or rating and selected value is submitted or skipped
|
||||
|
||||
@@ -71,7 +71,9 @@ export const generateQuestionAndFilterOptions = (
|
||||
questionFilterOptions.push({
|
||||
type: q.type,
|
||||
filterOptions: conditionOptions[q.type],
|
||||
filterComboBoxOptions: q?.choices ? q?.choices?.map((c) => c?.label) : [""],
|
||||
filterComboBoxOptions: q?.choices
|
||||
? q?.choices?.filter((c) => c.id !== "other")?.map((c) => c?.label)
|
||||
: [""],
|
||||
id: q.id,
|
||||
});
|
||||
} else if (q.type === TSurveyQuestionType.PictureSelection) {
|
||||
|
||||
@@ -31,6 +31,7 @@ interface ResponsePageProps {
|
||||
environmentTags: TTag[];
|
||||
attributes: TSurveyPersonAttributes;
|
||||
responsesPerPage: number;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
const ResponsePage = ({
|
||||
@@ -42,11 +43,13 @@ const ResponsePage = ({
|
||||
environmentTags,
|
||||
attributes,
|
||||
responsesPerPage,
|
||||
totalResponseCount,
|
||||
}: ResponsePageProps) => {
|
||||
const [responses, setResponses] = useState<TResponse[]>([]);
|
||||
const [page, setPage] = useState<number>(1);
|
||||
const [hasMore, setHasMore] = useState<boolean>(true);
|
||||
const [responseCount, setResponseCount] = useState<number | null>(null);
|
||||
const [isFetchingFirstPage, setFetchingFirstPage] = useState<boolean>(true);
|
||||
|
||||
const { selectedFilter, dateRange, resetState } = useResponseFilter();
|
||||
|
||||
@@ -82,17 +85,6 @@ const ResponsePage = ({
|
||||
}
|
||||
}, [searchParams, resetState]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchInitialResponses = async () => {
|
||||
const responses = await getResponsesBySurveySharingKeyAction(sharingKey, 1, responsesPerPage, filters);
|
||||
if (responses.length < responsesPerPage) {
|
||||
setHasMore(false);
|
||||
}
|
||||
setResponses(responses);
|
||||
};
|
||||
fetchInitialResponses();
|
||||
}, [filters, responsesPerPage, sharingKey]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResponsesCount = async () => {
|
||||
const responseCount = await getResponseCountBySurveySharingKeyAction(sharingKey, filters);
|
||||
@@ -101,6 +93,27 @@ const ResponsePage = ({
|
||||
handleResponsesCount();
|
||||
}, [filters, sharingKey]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchInitialResponses = async () => {
|
||||
try {
|
||||
setFetchingFirstPage(true);
|
||||
const responses = await getResponsesBySurveySharingKeyAction(
|
||||
sharingKey,
|
||||
1,
|
||||
responsesPerPage,
|
||||
filters
|
||||
);
|
||||
if (responses.length < responsesPerPage) {
|
||||
setHasMore(false);
|
||||
}
|
||||
setResponses(responses);
|
||||
} finally {
|
||||
setFetchingFirstPage(false);
|
||||
}
|
||||
};
|
||||
fetchInitialResponses();
|
||||
}, [filters, responsesPerPage, sharingKey]);
|
||||
|
||||
return (
|
||||
<ContentWrapper>
|
||||
<SummaryHeader survey={survey} product={product} />
|
||||
@@ -120,6 +133,9 @@ const ResponsePage = ({
|
||||
environmentTags={environmentTags}
|
||||
fetchNextPage={fetchNextPage}
|
||||
hasMore={hasMore}
|
||||
isFetchingFirstPage={isFetchingFirstPage}
|
||||
responseCount={responseCount}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</ContentWrapper>
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import { TSurvey } from "@formbricks/types/surveys";
|
||||
import { TTag } from "@formbricks/types/tags";
|
||||
import EmptySpaceFiller from "@formbricks/ui/EmptySpaceFiller";
|
||||
import SingleResponseCard from "@formbricks/ui/SingleResponseCard";
|
||||
import { SkeletonLoader } from "@formbricks/ui/SkeletonLoader";
|
||||
|
||||
interface ResponseTimelineProps {
|
||||
environment: TEnvironment;
|
||||
@@ -20,6 +21,9 @@ interface ResponseTimelineProps {
|
||||
environmentTags: TTag[];
|
||||
fetchNextPage: () => void;
|
||||
hasMore: boolean;
|
||||
isFetchingFirstPage: boolean;
|
||||
responseCount: number | null;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
export default function ResponseTimeline({
|
||||
@@ -29,6 +33,9 @@ export default function ResponseTimeline({
|
||||
environmentTags,
|
||||
fetchNextPage,
|
||||
hasMore,
|
||||
isFetchingFirstPage,
|
||||
responseCount,
|
||||
totalResponseCount,
|
||||
}: ResponseTimelineProps) {
|
||||
const loadingRef = useRef(null);
|
||||
|
||||
@@ -62,11 +69,14 @@ export default function ResponseTimeline({
|
||||
<div className="space-y-4">
|
||||
{survey.type === "web" && responses.length === 0 && !environment.widgetSetupCompleted ? (
|
||||
<EmptyInAppSurveys environment={environment} />
|
||||
) : responses.length === 0 ? (
|
||||
) : isFetchingFirstPage ? (
|
||||
<SkeletonLoader type="response" />
|
||||
) : responseCount === 0 ? (
|
||||
<EmptySpaceFiller
|
||||
type="response"
|
||||
environment={environment}
|
||||
noWidgetRequired={survey.type === "link"}
|
||||
emptyMessage={totalResponseCount === 0 ? undefined : "No response matches your filter"}
|
||||
/>
|
||||
) : (
|
||||
<div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { notFound } from "next/navigation";
|
||||
import { RESPONSES_PER_PAGE, REVALIDATION_INTERVAL, WEBAPP_URL } from "@formbricks/lib/constants";
|
||||
import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
|
||||
import { getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getResponseCountBySurveyId, getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getSurvey, getSurveyIdByResultShareKey } from "@formbricks/lib/survey/service";
|
||||
import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service";
|
||||
|
||||
@@ -35,6 +35,7 @@ export default async function Page({ params }) {
|
||||
|
||||
const tags = await getTagsByEnvironmentId(environment.id);
|
||||
const attributes = await getResponsePersonAttributes(surveyId);
|
||||
const totalResponseCount = await getResponseCountBySurveyId(surveyId);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -48,6 +49,7 @@ export default async function Page({ params }) {
|
||||
environmentTags={tags}
|
||||
attributes={attributes}
|
||||
responsesPerPage={RESPONSES_PER_PAGE}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -46,6 +46,7 @@ interface SummaryPageProps {
|
||||
sharingKey: string;
|
||||
environmentTags: TTag[];
|
||||
attributes: TSurveyPersonAttributes;
|
||||
totalResponseCount: number;
|
||||
}
|
||||
|
||||
const SummaryPage = ({
|
||||
@@ -56,12 +57,15 @@ const SummaryPage = ({
|
||||
sharingKey,
|
||||
environmentTags,
|
||||
attributes,
|
||||
totalResponseCount,
|
||||
}: SummaryPageProps) => {
|
||||
const [responseCount, setResponseCount] = useState<number | null>(null);
|
||||
|
||||
const { selectedFilter, dateRange, resetState } = useResponseFilter();
|
||||
const [surveySummary, setSurveySummary] = useState<TSurveySummary>(initialSurveySummary);
|
||||
const [showDropOffs, setShowDropOffs] = useState<boolean>(false);
|
||||
const [isFetchingSummary, setFetchingSummary] = useState<boolean>(true);
|
||||
|
||||
const { selectedFilter, dateRange, resetState } = useResponseFilter();
|
||||
|
||||
const filters = useMemo(
|
||||
() => getFormattedFilters(survey, selectedFilter, dateRange),
|
||||
@@ -70,14 +74,19 @@ const SummaryPage = ({
|
||||
|
||||
useEffect(() => {
|
||||
const handleInitialData = async () => {
|
||||
const responseCount = await getResponseCountBySurveySharingKeyAction(sharingKey, filters);
|
||||
setResponseCount(responseCount);
|
||||
if (responseCount === 0) {
|
||||
setSurveySummary(initialSurveySummary);
|
||||
return;
|
||||
try {
|
||||
setFetchingSummary(true);
|
||||
const responseCount = await getResponseCountBySurveySharingKeyAction(sharingKey, filters);
|
||||
setResponseCount(responseCount);
|
||||
if (responseCount === 0) {
|
||||
setSurveySummary(initialSurveySummary);
|
||||
return;
|
||||
}
|
||||
const response = await getSummaryBySurveySharingKeyAction(sharingKey, filters);
|
||||
setSurveySummary(response);
|
||||
} finally {
|
||||
setFetchingSummary(false);
|
||||
}
|
||||
const response = await getSummaryBySurveySharingKeyAction(sharingKey, filters);
|
||||
setSurveySummary(response);
|
||||
};
|
||||
|
||||
handleInitialData();
|
||||
@@ -119,6 +128,8 @@ const SummaryPage = ({
|
||||
responseCount={responseCount}
|
||||
survey={survey}
|
||||
environment={environment}
|
||||
fetchingSummary={isFetchingSummary}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</ContentWrapper>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { notFound } from "next/navigation";
|
||||
import { REVALIDATION_INTERVAL } from "@formbricks/lib/constants";
|
||||
import { getEnvironment } from "@formbricks/lib/environment/service";
|
||||
import { getProductByEnvironmentId } from "@formbricks/lib/product/service";
|
||||
import { getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getResponseCountBySurveyId, getResponsePersonAttributes } from "@formbricks/lib/response/service";
|
||||
import { getSurvey, getSurveyIdByResultShareKey } from "@formbricks/lib/survey/service";
|
||||
import { getTagsByEnvironmentId } from "@formbricks/lib/tag/service";
|
||||
|
||||
@@ -35,6 +35,7 @@ export default async function Page({ params }) {
|
||||
|
||||
const tags = await getTagsByEnvironmentId(environment.id);
|
||||
const attributes = await getResponsePersonAttributes(surveyId);
|
||||
const totalResponseCount = await getResponseCountBySurveyId(surveyId);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -46,6 +47,7 @@ export default async function Page({ params }) {
|
||||
product={product}
|
||||
environmentTags={tags}
|
||||
attributes={attributes}
|
||||
totalResponseCount={totalResponseCount}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -67,7 +67,9 @@ const EmptySpaceFiller: React.FC<EmptySpaceFillerProps> = ({
|
||||
</Link>
|
||||
)}
|
||||
{(environment.widgetSetupCompleted || noWidgetRequired) && (
|
||||
<span className="bg-light-background-primary-500 text-center">Waiting for a response 🧘♂️</span>
|
||||
<span className="bg-light-background-primary-500 text-center">
|
||||
{emptyMessage ?? "Waiting for a response"} 🧘♂️
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="h-12 w-full rounded-full bg-slate-50/50"></div>
|
||||
|
||||
43
packages/ui/SkeletonLoader/index.tsx
Normal file
43
packages/ui/SkeletonLoader/index.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Skeleton } from "../Skeleton";
|
||||
|
||||
type SkeletonLoaderProps = {
|
||||
type: "response" | "summary";
|
||||
};
|
||||
|
||||
export function SkeletonLoader({ type }: SkeletonLoaderProps) {
|
||||
if (type === "summary") {
|
||||
return (
|
||||
<div className="rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
|
||||
<Skeleton className="group space-y-4 rounded-lg bg-white p-6 ">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className=" h-6 w-full rounded-full bg-slate-100"></div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div className="flex gap-4">
|
||||
<div className="h-6 w-24 rounded-full bg-slate-100"></div>
|
||||
<div className="h-6 w-24 rounded-full bg-slate-100"></div>
|
||||
</div>
|
||||
<div className=" flex h-12 w-full items-center justify-center rounded-full bg-slate-50 text-sm text-slate-500 hover:bg-slate-100"></div>
|
||||
<div className="h-12 w-full rounded-full bg-slate-50/50"></div>
|
||||
</div>
|
||||
</Skeleton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === "response") {
|
||||
return (
|
||||
<div className="group space-y-4 rounded-lg bg-white p-6 ">
|
||||
<div className="flex items-center space-x-4">
|
||||
<Skeleton className="h-12 w-12 flex-shrink-0 rounded-full bg-slate-100"></Skeleton>
|
||||
<Skeleton className=" h-6 w-full rounded-full bg-slate-100"></Skeleton>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<Skeleton className="h-12 w-full rounded-full bg-slate-100"></Skeleton>
|
||||
<Skeleton className=" flex h-12 w-full items-center justify-center rounded-full bg-slate-50 text-sm text-slate-500 hover:bg-slate-100"></Skeleton>
|
||||
<Skeleton className="h-12 w-full rounded-full bg-slate-50/50"></Skeleton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user