diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/page.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/page.tsx index a9005f656a..83d85b518c 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/page.tsx @@ -13,7 +13,7 @@ import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; import { getSurveyCount } from "@formbricks/lib/survey/service"; import { getTeamByEnvironmentId } from "@formbricks/lib/team/service"; import ContentWrapper from "@formbricks/ui/ContentWrapper"; -import SurveysList from "@formbricks/ui/SurveysList"; +import { SurveysList } from "@formbricks/ui/SurveysList"; export const metadata: Metadata = { title: "Your Surveys", diff --git a/packages/lib/constants.ts b/packages/lib/constants.ts index 1e1b71fe14..92a10062bf 100644 --- a/packages/lib/constants.ts +++ b/packages/lib/constants.ts @@ -79,7 +79,7 @@ export const MAIL_FROM = env.MAIL_FROM; export const NEXTAUTH_SECRET = env.NEXTAUTH_SECRET; export const ITEMS_PER_PAGE = 50; -export const SURVEYS_PER_PAGE = 20; +export const SURVEYS_PER_PAGE = 12; export const RESPONSES_PER_PAGE = 10; export const TEXT_RESPONSES_PER_PAGE = 5; diff --git a/packages/lib/response/util.ts b/packages/lib/response/util.ts index 13753b1920..b2e69eaaad 100644 --- a/packages/lib/response/util.ts +++ b/packages/lib/response/util.ts @@ -37,7 +37,7 @@ export function calculateTtcTotal(ttc: TResponseTtc) { } export const buildWhereClause = (filterCriteria?: TResponseFilterCriteria) => { - const whereClause: Record[] = []; + const whereClause: Prisma.ResponseWhereInput["AND"] = []; // For finished if (filterCriteria?.finished !== undefined) { diff --git a/packages/lib/survey/service.ts b/packages/lib/survey/service.ts index 63c8a0448e..11b5ed5cdb 100644 --- a/packages/lib/survey/service.ts +++ b/packages/lib/survey/service.ts @@ -11,7 +11,12 @@ import { ZId } from "@formbricks/types/environment"; import { DatabaseError, InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors"; import { TPerson } from "@formbricks/types/people"; import { TSegment, ZSegment, ZSegmentFilters } from "@formbricks/types/segment"; -import { TSurvey, TSurveyInput, ZSurveyWithRefinements } from "@formbricks/types/surveys"; +import { + TSurvey, + TSurveyFilterCriteria, + TSurveyInput, + ZSurveyWithRefinements, +} from "@formbricks/types/surveys"; import { getActionsByPersonId } from "../action/service"; import { getActionClasses } from "../actionClass/service"; @@ -31,7 +36,7 @@ import { subscribeTeamMembersToSurveyResponses } from "../team/service"; import { diffInDays, formatDateFields } from "../utils/datetime"; import { validateInputs } from "../utils/validate"; import { surveyCache } from "./cache"; -import { anySurveyHasFilters, formatSurveyDateFields } from "./util"; +import { anySurveyHasFilters, buildOrderByClause, buildWhereClause, formatSurveyDateFields } from "./util"; interface TriggerUpdate { create?: Array<{ actionClassId: string }>; @@ -283,7 +288,8 @@ export const getSurveysByActionClassId = async (actionClassId: string, page?: nu export const getSurveys = async ( environmentId: string, limit?: number, - offset?: number + offset?: number, + filterCriteria?: TSurveyFilterCriteria ): Promise => { const surveys = await unstable_cache( async () => { @@ -294,13 +300,10 @@ export const getSurveys = async ( surveysPrisma = await prisma.survey.findMany({ where: { environmentId, + ...buildWhereClause(filterCriteria), }, select: selectSurvey, - orderBy: [ - { - updatedAt: "desc", - }, - ], + orderBy: buildOrderByClause(filterCriteria?.sortBy), take: limit ? limit : undefined, skip: offset ? offset : undefined, }); @@ -335,7 +338,7 @@ export const getSurveys = async ( } return surveys; }, - [`getSurveys-${environmentId}-${limit}-${offset}`], + [`getSurveys-${environmentId}-${limit}-${offset}-${JSON.stringify(filterCriteria)}`], { tags: [surveyCache.tag.byEnvironmentId(environmentId)], revalidate: SERVICES_REVALIDATION_INTERVAL, diff --git a/packages/lib/survey/util.ts b/packages/lib/survey/util.ts index eba333eeed..0c816bf4fa 100644 --- a/packages/lib/survey/util.ts +++ b/packages/lib/survey/util.ts @@ -1,8 +1,10 @@ import "server-only"; +import { Prisma } from "@prisma/client"; + import { TLegacySurvey } from "@formbricks/types/LegacySurvey"; import { TPerson } from "@formbricks/types/people"; -import { TSurvey } from "@formbricks/types/surveys"; +import { TSurvey, TSurveyFilterCriteria } from "@formbricks/types/surveys"; export const formatSurveyDateFields = (survey: TSurvey): TSurvey => { if (typeof survey.createdAt === "string") { @@ -42,6 +44,53 @@ export const formatSurveyDateFields = (survey: TSurvey): TSurvey => { return survey; }; +export const buildWhereClause = (filterCriteria?: TSurveyFilterCriteria) => { + const whereClause: Prisma.SurveyWhereInput["AND"] = []; + + // for name + if (filterCriteria?.name) { + whereClause.push({ name: { contains: filterCriteria.name, mode: "insensitive" } }); + } + + // for status + if (filterCriteria?.status && filterCriteria?.status?.length) { + whereClause.push({ status: { in: filterCriteria.status } }); + } + + // for type + if (filterCriteria?.type && filterCriteria?.type?.length) { + whereClause.push({ type: { in: filterCriteria.type } }); + } + + // for createdBy + if (filterCriteria?.createdBy?.value && filterCriteria?.createdBy?.value?.length) { + if (filterCriteria.createdBy.value.length === 1) { + if (filterCriteria.createdBy.value[0] === "you") { + whereClause.push({ createdBy: filterCriteria.createdBy.userId }); + } + if (filterCriteria.createdBy.value[0] === "others") { + whereClause.push({ createdBy: { not: filterCriteria.createdBy.userId } }); + } + } + } + + return { AND: whereClause }; +}; + +export const buildOrderByClause = ( + sortBy?: TSurveyFilterCriteria["sortBy"] +): Prisma.SurveyOrderByWithRelationInput[] | undefined => { + if (!sortBy) { + return undefined; + } + + if (sortBy === "name") { + return [{ name: "asc" }]; + } + + return [{ [sortBy]: "desc" }]; +}; + export const anySurveyHasFilters = (surveys: TSurvey[] | TLegacySurvey[]): boolean => { return surveys.some((survey) => { if ("segment" in survey && survey.segment) { diff --git a/packages/types/surveys.ts b/packages/types/surveys.ts index 38ce1c99c2..eb21298ffc 100644 --- a/packages/types/surveys.ts +++ b/packages/types/surveys.ts @@ -580,4 +580,43 @@ export interface TSurveyQuestionSummary { }[]; } +export const ZSurveyFilterCriteria = z.object({ + name: z.string().optional(), + status: z.array(ZSurveyStatus).optional(), + type: z.array(ZSurveyType).optional(), + createdBy: z + .object({ + userId: z.string(), + value: z.array(z.enum(["you", "others"])), + }) + .optional(), + sortBy: z.enum(["createdAt", "updatedAt", "name"]).optional(), +}); + +export type TSurveyFilterCriteria = z.infer; + +const ZSurveyFilters = z.object({ + name: z.string(), + createdBy: z.array(z.enum(["you", "others"])), + status: z.array(ZSurveyStatus), + type: z.array(ZSurveyType), + sortBy: z.enum(["createdAt", "updatedAt", "name"]), +}); + +export type TSurveyFilters = z.infer; + export type TSurveyEditorTabs = "questions" | "settings" | "styling"; + +const ZFilterOption = z.object({ + label: z.string(), + value: z.string(), +}); + +export type TFilterOption = z.infer; + +const ZSortOption = z.object({ + label: z.string(), + value: z.enum(["createdAt", "updatedAt", "name"]), +}); + +export type TSortOption = z.infer; diff --git a/packages/ui/SurveysList/actions.ts b/packages/ui/SurveysList/actions.ts index ce0de7a8f9..18fc021c3c 100644 --- a/packages/ui/SurveysList/actions.ts +++ b/packages/ui/SurveysList/actions.ts @@ -11,6 +11,7 @@ import { surveyCache } from "@formbricks/lib/survey/cache"; import { deleteSurvey, duplicateSurvey, getSurvey, getSurveys } from "@formbricks/lib/survey/service"; import { generateSurveySingleUseId } from "@formbricks/lib/utils/singleUseSurveys"; import { AuthorizationError, ResourceNotFoundError } from "@formbricks/types/errors"; +import { TSurveyFilterCriteria } from "@formbricks/types/surveys"; export const getSurveyAction = async (surveyId: string) => { const session = await getServerSession(authOptions); @@ -22,7 +23,7 @@ export const getSurveyAction = async (surveyId: string) => { return await getSurvey(surveyId); }; -export async function duplicateSurveyAction(environmentId: string, surveyId: string) { +export const duplicateSurveyAction = async (environmentId: string, surveyId: string) => { const session = await getServerSession(authOptions); if (!session) throw new AuthorizationError("Not authorized"); @@ -31,13 +32,13 @@ export async function duplicateSurveyAction(environmentId: string, surveyId: str const duplicatedSurvey = await duplicateSurvey(environmentId, surveyId, session.user.id); return duplicatedSurvey; -} +}; -export async function copyToOtherEnvironmentAction( +export const copyToOtherEnvironmentAction = async ( environmentId: string, surveyId: string, targetEnvironmentId: string -) { +) => { const session = await getServerSession(authOptions); if (!session) throw new AuthorizationError("Not authorized"); @@ -195,7 +196,7 @@ export async function copyToOtherEnvironmentAction( environmentId: targetEnvironmentId, }); return newSurvey; -} +}; export const deleteSurveyAction = async (surveyId: string) => { const session = await getServerSession(authOptions); @@ -212,7 +213,7 @@ export const deleteSurveyAction = async (surveyId: string) => { await deleteSurvey(surveyId); }; -export async function generateSingleUseIdAction(surveyId: string, isEncrypted: boolean): Promise { +export const generateSingleUseIdAction = async (surveyId: string, isEncrypted: boolean): Promise => { const session = await getServerSession(authOptions); if (!session) throw new AuthorizationError("Not authorized"); @@ -221,14 +222,19 @@ export async function generateSingleUseIdAction(surveyId: string, isEncrypted: b if (!hasUserSurveyAccess) throw new AuthorizationError("Not authorized"); return generateSurveySingleUseId(isEncrypted); -} +}; -export async function getSurveysAction(environmentId: string, limit?: number, offset?: number) { +export const getSurveysAction = async ( + environmentId: string, + limit?: number, + offset?: number, + filterCriteria?: TSurveyFilterCriteria +) => { const session = await getServerSession(authOptions); if (!session) throw new AuthorizationError("Not authorized"); const isAuthorized = await hasUserEnvironmentAccess(session.user.id, environmentId); if (!isAuthorized) throw new AuthorizationError("Not authorized"); - return await getSurveys(environmentId, limit, offset); -} + return await getSurveys(environmentId, limit, offset, filterCriteria); +}; diff --git a/packages/ui/SurveysList/components/SortOption.tsx b/packages/ui/SurveysList/components/SortOption.tsx new file mode 100644 index 0000000000..0afdd1cae3 --- /dev/null +++ b/packages/ui/SurveysList/components/SortOption.tsx @@ -0,0 +1,24 @@ +import { TSortOption, TSurveyFilters } from "@formbricks/types/surveys"; + +import { DropdownMenuItem } from "../../DropdownMenu"; + +interface SortOptionProps { + option: TSortOption; + sortBy: TSurveyFilters["sortBy"]; + handleSortChange: (option: TSortOption) => void; +} + +export const SortOption = ({ option, sortBy, handleSortChange }: SortOptionProps) => ( + { + handleSortChange(option); + }}> +
+ +

{option.label}

+
+
+); diff --git a/packages/ui/SurveysList/components/SurveyCard.tsx b/packages/ui/SurveysList/components/SurveyCard.tsx index 77be5205f8..909730fd86 100644 --- a/packages/ui/SurveysList/components/SurveyCard.tsx +++ b/packages/ui/SurveysList/components/SurveyCard.tsx @@ -9,7 +9,7 @@ import { TSurvey } from "@formbricks/types/surveys"; import { SurveyStatusIndicator } from "../../SurveyStatusIndicator"; import { generateSingleUseIdAction } from "../actions"; -import SurveyDropDownMenu from "./SurveyDropdownMenu"; +import { SurveyDropDownMenu } from "./SurveyDropdownMenu"; interface SurveyCardProps { survey: TSurvey; @@ -21,7 +21,7 @@ interface SurveyCardProps { duplicateSurvey: (survey: TSurvey) => void; deleteSurvey: (surveyId: string) => void; } -export default function SurveyCard({ +export const SurveyCard = ({ survey, environment, otherEnvironment, @@ -30,7 +30,7 @@ export default function SurveyCard({ orientation, deleteSurvey, duplicateSurvey, -}: SurveyCardProps) { +}: SurveyCardProps) => { const isSurveyCreationDeletionDisabled = isViewer; const surveyStatusLabel = useMemo(() => { @@ -119,7 +119,7 @@ export default function SurveyCard({ key={survey.id} className="relative grid w-full grid-cols-8 place-items-center gap-3 rounded-xl border border-slate-200 bg-white p-4 shadow-sm transition-all ease-in-out hover:scale-[101%]"> -
+
{survey.name}
); }; - if (orientation === "grid") return renderGridContent(); - else return renderListContent(); -} + + if (orientation === "grid") { + return renderGridContent(); + } else return renderListContent(); +}; diff --git a/packages/ui/SurveysList/components/SurveyDropdownMenu.tsx b/packages/ui/SurveysList/components/SurveyDropdownMenu.tsx index 5c7767e2e6..773d7cfc9f 100644 --- a/packages/ui/SurveysList/components/SurveyDropdownMenu.tsx +++ b/packages/ui/SurveysList/components/SurveyDropdownMenu.tsx @@ -38,7 +38,7 @@ interface SurveyDropDownMenuProps { deleteSurvey: (surveyId: string) => void; } -export default function SurveyDropDownMenu({ +export const SurveyDropDownMenu = ({ environmentId, survey, environment, @@ -48,7 +48,7 @@ export default function SurveyDropDownMenu({ isSurveyCreationDeletionDisabled, deleteSurvey, duplicateSurvey, -}: SurveyDropDownMenuProps) { +}: SurveyDropDownMenuProps) => { const [isDeleteDialogOpen, setDeleteDialogOpen] = useState(false); const [loading, setLoading] = useState(false); const [isDropDownOpen, setIsDropDownOpen] = useState(false); @@ -244,4 +244,4 @@ export default function SurveyDropDownMenu({ )}
); -} +}; diff --git a/packages/ui/SurveysList/components/SurveyFilterDropdown.tsx b/packages/ui/SurveysList/components/SurveyFilterDropdown.tsx new file mode 100644 index 0000000000..32f5ed5a1f --- /dev/null +++ b/packages/ui/SurveysList/components/SurveyFilterDropdown.tsx @@ -0,0 +1,59 @@ +import { ChevronDownIcon } from "lucide-react"; + +import { TFilterOption } from "@formbricks/types/surveys"; + +import { Checkbox } from "../../Checkbox"; +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../DropdownMenu"; + +interface SurveyFilterDropdownProps { + title: string; + id: "createdBy" | "status" | "type"; + options: TFilterOption[]; + selectedOptions: string[]; + setSelectedOptions: (value: string) => void; + isOpen: boolean; + toggleDropdown: (id: string) => void; +} + +export const SurveyFilterDropdown = ({ + title, + id, + options, + selectedOptions, + setSelectedOptions, + isOpen, + toggleDropdown, +}: SurveyFilterDropdownProps) => { + const triggerClasses = `surveyFilterDropdown min-w-auto h-8 rounded-md border border-slate-700 sm:px-2 cursor-pointer outline-none + ${selectedOptions.length > 0 ? "bg-slate-900 text-white" : "hover:bg-slate-900"}`; + + return ( + toggleDropdown(id)}> + +
+ {title} + +
+
+ + {options.map((option) => ( + { + e.preventDefault(); + setSelectedOptions(option.value); + }}> +
+ +

{option.label}

+
+
+ ))} +
+
+ ); +}; diff --git a/packages/ui/SurveysList/components/SurveyFilters.tsx b/packages/ui/SurveysList/components/SurveyFilters.tsx index 7cfadfe021..8d9c02ab3d 100644 --- a/packages/ui/SurveysList/components/SurveyFilters.tsx +++ b/packages/ui/SurveysList/components/SurveyFilters.tsx @@ -1,76 +1,52 @@ import { ChevronDownIcon, Equal, Grid2X2, Search, X } from "lucide-react"; -import { useEffect, useState } from "react"; +import { useState } from "react"; +import { useDebounce } from "react-use"; -import { TSurvey } from "@formbricks/types/surveys"; +import { TFilterOption, TSortOption, TSurveyFilters } from "@formbricks/types/surveys"; +import { initialFilters } from ".."; import { Button } from "../../Button"; -import { Checkbox } from "../../Checkbox"; -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../DropdownMenu"; +import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "../../DropdownMenu"; import { TooltipRenderer } from "../../Tooltip"; +import { SortOption } from "./SortOption"; +import { SurveyFilterDropdown } from "./SurveyFilterDropdown"; interface SurveyFilterProps { - surveys: TSurvey[]; - setFilteredSurveys: (surveys: TSurvey[]) => void; orientation: string; setOrientation: (orientation: string) => void; - userId: string; -} -interface TFilterOption { - label: string; - value: string; -} -interface TSortOption { - label: string; - sortFunction: (a: TSurvey, b: TSurvey) => number; + surveyFilters: TSurveyFilters; + setSurveyFilters: React.Dispatch>; } -interface FilterDropdownProps { - title: string; - id: string; - options: TFilterOption[]; - selectedOptions: string[]; - setSelectedOptions: (options: string[]) => void; - isOpen: boolean; -} +const creatorOptions: TFilterOption[] = [ + { label: "You", value: "you" }, + { label: "Others", value: "others" }, +]; -const statusOptions = [ +const statusOptions: TFilterOption[] = [ { label: "In Progress", value: "inProgress" }, { label: "Scheduled", value: "scheduled" }, { label: "Paused", value: "paused" }, { label: "Completed", value: "completed" }, { label: "Draft", value: "draft" }, ]; -const typeOptions = [ +const typeOptions: TFilterOption[] = [ { label: "Link", value: "link" }, { label: "In-app", value: "web" }, ]; -const sortOptions = [ +const sortOptions: TSortOption[] = [ { label: "Last Modified", - sortFunction: (a: TSurvey, b: TSurvey) => { - const dateA = new Date(a.updatedAt); - const dateB = new Date(b.updatedAt); - if (!isNaN(dateA.getTime()) && !isNaN(dateB.getTime())) { - return dateB.getTime() - dateA.getTime(); - } - return 0; - }, + value: "updatedAt", }, { label: "Created On", - sortFunction: (a: TSurvey, b: TSurvey) => { - const dateA = new Date(a.createdAt); - const dateB = new Date(b.createdAt); - if (!isNaN(dateA.getTime()) && !isNaN(dateB.getTime())) { - return dateB.getTime() - dateA.getTime(); - } - return 0; - }, + value: "createdAt", }, { label: "Alphabetical", - sortFunction: (a: TSurvey, b: TSurvey) => a.name.localeCompare(b.name), + value: "name", }, // Add other sorting options as needed ]; @@ -79,129 +55,66 @@ const getToolTipContent = (orientation: string) => { return
{orientation} View
; }; -export default function SurveyFilters({ - surveys, - setFilteredSurveys, +export const SurveyFilters = ({ orientation, setOrientation, - userId, -}: SurveyFilterProps) { - const [createdByFilter, setCreatedByFilter] = useState([]); - const [statusFilters, setStatusFilters] = useState([]); - const [typeFilters, setTypeFilters] = useState([]); - const [sortBy, setSortBy] = useState(sortOptions[0]); - const [searchTerm, setSearchTerm] = useState(""); + surveyFilters, + setSurveyFilters, +}: SurveyFilterProps) => { + const { createdBy, sortBy, status, type } = surveyFilters; + const [name, setName] = useState(""); + + useDebounce(() => setSurveyFilters((prev) => ({ ...prev, name: name })), 800, [name]); + const [dropdownOpenStates, setDropdownOpenStates] = useState(new Map()); const toggleDropdown = (id: string) => { setDropdownOpenStates(new Map(dropdownOpenStates).set(id, !dropdownOpenStates.get(id))); }; - const creatorOptions = [ - { label: "You", value: userId }, - { label: "Others", value: "other" }, - ]; - - useEffect(() => { - let filtered = [...surveys]; - - // Filter by search term - if (searchTerm) { - filtered = filtered.filter((survey) => survey.name.toLowerCase().includes(searchTerm.toLowerCase())); - } - - if (createdByFilter.length > 0) { - filtered = filtered.filter((survey) => { - if (survey.createdBy) { - if (createdByFilter.length === 2) return true; - if (createdByFilter.includes("other")) return survey.createdBy !== userId; - else { - return survey.createdBy === userId; - } - } - }); - } - - if (statusFilters.length > 0) { - filtered = filtered.filter((survey) => statusFilters.includes(survey.status)); - } - if (typeFilters.length > 0) { - filtered = filtered.filter((survey) => typeFilters.includes(survey.type)); - } - if (sortBy && sortBy.sortFunction) { - filtered.sort(sortBy.sortFunction); - } - - setFilteredSurveys(filtered); - }, [createdByFilter, statusFilters, typeFilters, sortBy, searchTerm, surveys]); - - const handleFilterChange = ( - value: string, - selectedOptions: string[], - setSelectedOptions: (options: string[]) => void - ) => { - if (selectedOptions.includes(value)) { - setSelectedOptions(selectedOptions.filter((option) => option !== value)); - } else { - setSelectedOptions([...selectedOptions, value]); + const handleCreatedByChange = (value: string) => { + if (value === "you" || value === "others") { + if (createdBy.includes(value)) { + setSurveyFilters((prev) => ({ ...prev, createdBy: prev.createdBy.filter((v) => v !== value) })); + } else { + setSurveyFilters((prev) => ({ ...prev, createdBy: [...prev.createdBy, value] })); + } } }; - const renderSortOption = (option: TSortOption) => ( - { - setSortBy(option); - }}> -
- -

{option.label}

-
-
- ); + const handleStatusChange = (value: string) => { + if ( + value === "inProgress" || + value === "paused" || + value === "completed" || + value === "draft" || + value === "scheduled" + ) { + if (status.includes(value)) { + setSurveyFilters((prev) => ({ ...prev, status: prev.status.filter((v) => v !== value) })); + } else { + setSurveyFilters((prev) => ({ ...prev, status: [...prev.status, value] })); + } + } + }; - const FilterDropdown = ({ - title, - id, - options, - selectedOptions, - setSelectedOptions, - isOpen, - }: FilterDropdownProps) => { - const triggerClasses = `surveyFilterDropdown min-w-auto h-8 rounded-md border border-slate-700 sm:px-2 cursor-pointer outline-none - ${selectedOptions.length > 0 ? "bg-slate-900 text-white" : "hover:bg-slate-900"}`; + const handleTypeChange = (value: string) => { + if (value === "link" || value === "web") { + if (type.includes(value)) { + setSurveyFilters((prev) => ({ ...prev, type: prev.type.filter((v) => v !== value) })); + } else { + setSurveyFilters((prev) => ({ ...prev, type: [...prev.type, value] })); + } + } + }; - return ( - toggleDropdown(id)}> - -
- {title} - -
-
- - {options.map((option) => ( - { - e.preventDefault(); - handleFilterChange(option.value, selectedOptions, setSelectedOptions); - }}> -
- -

{option.label}

-
-
- ))} -
-
- ); + const handleSortChange = (option: TSortOption) => { + setSurveyFilters((prev) => ({ ...prev, sortBy: option.value })); + }; + + const handleOrientationChange = (value: string) => { + setOrientation(value); + localStorage.setItem("surveyOrientation", value); }; return ( @@ -213,49 +126,51 @@ export default function SurveyFilters({ type="text" className="border-none bg-transparent placeholder:text-sm" placeholder="Search by survey name" - value={searchTerm} - onChange={(e) => setSearchTerm(e.target.value)} + value={name} + onChange={(e) => setName(e.target.value)} />
-
-
-
- {(createdByFilter.length > 0 || statusFilters.length > 0 || typeFilters.length > 0) && ( + + {(createdBy.length > 0 || status.length > 0 || type.length > 0) && ( - {filteredSurveys.length > 0 ? ( + {surveys.length > 0 ? (
{orientation === "list" && (
@@ -104,7 +124,7 @@ export default function SurveysList({
Updated at
- {filteredSurveys.map((survey) => { + {surveys.map((survey) => { return ( - {filteredSurveys.map((survey) => { + {surveys.map((survey) => { return ( ); -} +}; diff --git a/packages/ui/SurveysList/util.ts b/packages/ui/SurveysList/util.ts new file mode 100644 index 0000000000..216a9c4543 --- /dev/null +++ b/packages/ui/SurveysList/util.ts @@ -0,0 +1,30 @@ +import { TSurveyFilterCriteria, TSurveyFilters } from "@formbricks/types/surveys"; + +export const getFormattedFilters = (surveyFilters: TSurveyFilters, userId: string): TSurveyFilterCriteria => { + const filters: TSurveyFilterCriteria = {}; + + if (surveyFilters.name) { + filters.name = surveyFilters.name; + } + + if (surveyFilters.status && surveyFilters.status.length) { + filters.status = surveyFilters.status; + } + + if (surveyFilters.type && surveyFilters.type.length) { + filters.type = surveyFilters.type; + } + + if (surveyFilters.createdBy && surveyFilters.createdBy.length) { + filters.createdBy = { + userId: userId, + value: surveyFilters.createdBy, + }; + } + + if (surveyFilters.sortBy) { + filters.sortBy = surveyFilters.sortBy; + } + + return filters; +};