From 0cc8cdf52a86ded395adf8f30bd023288f35b6f9 Mon Sep 17 00:00:00 2001 From: Matti Nannt Date: Sun, 22 Oct 2023 18:55:59 +0200 Subject: [PATCH] chore: remove swr from dependencies (#1407) --- .../surveys/components/SurveyList.tsx | 17 ++- .../surveys/components/SurveyStarter.tsx | 4 + .../surveys/templates/TemplateContainer.tsx | 4 + .../surveys/templates/TemplateList.tsx | 18 ++- .../surveys/templates/page.tsx | 23 +++- apps/web/app/lib/members.ts | 113 ------------------ apps/web/app/lib/profile.ts | 26 ---- .../app/lib/responseNotes/responsesNotes.ts | 21 ---- apps/web/app/lib/utils.ts | 34 ------ apps/web/package.json | 1 - packages/lib/profile/service.ts | 1 + packages/types/profile.ts | 5 +- pnpm-lock.yaml | 13 -- 13 files changed, 55 insertions(+), 225 deletions(-) delete mode 100644 apps/web/app/lib/members.ts delete mode 100644 apps/web/app/lib/profile.ts delete mode 100644 apps/web/app/lib/responseNotes/responsesNotes.ts diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyList.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyList.tsx index 794644d860..20ee9f4234 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyList.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyList.tsx @@ -11,9 +11,17 @@ import { Badge } from "@formbricks/ui/Badge"; import { ComputerDesktopIcon, LinkIcon, PlusIcon } from "@heroicons/react/24/solid"; import Link from "next/link"; import { generateSurveySingleUseId } from "@/app/lib/singleUseSurveys"; +import { getServerSession } from "next-auth"; +import { authOptions } from "@formbricks/lib/authOptions"; export default async function SurveysList({ environmentId }: { environmentId: string }) { + const session = await getServerSession(authOptions); const product = await getProductByEnvironmentId(environmentId); + + if (!session) { + throw new Error("Session not found"); + } + if (!product) { throw new Error("Product not found"); } @@ -28,7 +36,14 @@ export default async function SurveysList({ environmentId }: { environmentId: st const otherEnvironment = environments.find((e) => e.type !== environment.type)!; if (surveys.length === 0) { - return ; + return ( + + ); } return ( diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyStarter.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyStarter.tsx index df79d1c222..e068a1f7a6 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyStarter.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/components/SurveyStarter.tsx @@ -9,15 +9,18 @@ import { TTemplate } from "@formbricks/types/templates"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { toast } from "react-hot-toast"; +import { TProfile } from "@formbricks/types/profile"; export default function SurveyStarter({ environmentId, environment, product, + profile, }: { environmentId: string; environment: TEnvironment; product: TProduct; + profile: TProfile; }) { const [isCreateSurveyLoading, setIsCreateSurveyLoading] = useState(false); const router = useRouter(); @@ -56,6 +59,7 @@ export default function SurveyStarter({ }} environment={environment} product={product} + profile={profile} /> )} diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateContainer.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateContainer.tsx index f74fd9ca93..57990b5754 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateContainer.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateContainer.tsx @@ -10,17 +10,20 @@ import TemplateList from "./TemplateList"; import type { TProduct } from "@formbricks/types/product"; import type { TEnvironment } from "@formbricks/types/environment"; import { SearchBox } from "@formbricks/ui/SearchBox"; +import { TProfile } from "@formbricks/types/profile"; type TemplateContainerWithPreviewProps = { environmentId: string; product: TProduct; environment: TEnvironment; + profile: TProfile; }; export default function TemplateContainerWithPreview({ environmentId, product, environment, + profile, }: TemplateContainerWithPreviewProps) { const [activeTemplate, setActiveTemplate] = useState(null); const [activeQuestionId, setActiveQuestionId] = useState(null); @@ -56,6 +59,7 @@ export default function TemplateContainerWithPreview({ environmentId={environmentId} environment={environment} product={product} + profile={profile} templateSearch={templateSearch ?? ""} onTemplateClick={(template) => { setActiveQuestionId(template.preset.questions[0].id); diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateList.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateList.tsx index e19b04e5be..244ca72a6c 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateList.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/TemplateList.tsx @@ -1,15 +1,14 @@ "use client"; -import LoadingSpinner from "@formbricks/ui/LoadingSpinner"; -import { useProfile } from "@/app/lib/profile"; import { replacePresetPlaceholders } from "@/app/lib/templates"; import { cn } from "@formbricks/lib/cn"; import type { TEnvironment } from "@formbricks/types/environment"; import type { TProduct } from "@formbricks/types/product"; +import { TProfile } from "@formbricks/types/profile"; +import { TSurveyInput } from "@formbricks/types/surveys"; import { TTemplate } from "@formbricks/types/templates"; -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui/Tooltip"; import { Button } from "@formbricks/ui/Button"; -import { ErrorComponent } from "@formbricks/ui/ErrorComponent"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@formbricks/ui/Tooltip"; import { PlusCircleIcon } from "@heroicons/react/24/outline"; import { SparklesIcon } from "@heroicons/react/24/solid"; import { SplitIcon } from "lucide-react"; @@ -17,10 +16,10 @@ import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { createSurveyAction } from "../actions"; import { customSurvey, templates } from "./templates"; -import { TSurveyInput } from "@formbricks/types/surveys"; type TemplateList = { environmentId: string; + profile: TProfile; onTemplateClick: (template: TTemplate) => void; environment: TEnvironment; product: TProduct; @@ -31,6 +30,7 @@ const ALL_CATEGORY_NAME = "All"; const RECOMMENDED_CATEGORY_NAME = "For you"; export default function TemplateList({ environmentId, + profile, onTemplateClick, product, environment, @@ -40,7 +40,6 @@ export default function TemplateList({ const [activeTemplate, setActiveTemplate] = useState(null); const [loading, setLoading] = useState(false); const [selectedFilter, setSelectedFilter] = useState(RECOMMENDED_CATEGORY_NAME); - const { profile, isLoadingProfile, isErrorProfile } = useProfile(); const [categories, setCategories] = useState>([]); @@ -78,14 +77,13 @@ export default function TemplateList({ router.push(`/environments/${environmentId}/surveys/${survey.id}/edit`); }; - if (isLoadingProfile) return ; - if (isErrorProfile) return ; - const filteredTemplates = templates.filter((template) => { const matchesCategory = selectedFilter === ALL_CATEGORY_NAME || template.category === selectedFilter || - (selectedFilter === RECOMMENDED_CATEGORY_NAME && template.objectives?.includes(profile.objective)); + (profile.objective && + selectedFilter === RECOMMENDED_CATEGORY_NAME && + template.objectives?.includes(profile.objective)); const templateName = template.name?.toLowerCase(); const templateDescription = template.description?.toLowerCase(); diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/page.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/page.tsx index 9d374f7822..8900194c3b 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/templates/page.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/templates/page.tsx @@ -1,11 +1,21 @@ -import TemplateContainerWithPreview from "./TemplateContainer"; +import { authOptions } from "@formbricks/lib/authOptions"; import { getEnvironment } from "@formbricks/lib/environment/service"; import { getProductByEnvironmentId } from "@formbricks/lib/product/service"; +import { getServerSession } from "next-auth"; +import TemplateContainerWithPreview from "./TemplateContainer"; export default async function SurveyTemplatesPage({ params }) { + const session = await getServerSession(authOptions); const environmentId = params.environmentId; - const environment = await getEnvironment(environmentId); - const product = await getProductByEnvironmentId(environmentId); + + const [environment, product] = await Promise.all([ + getEnvironment(environmentId), + getProductByEnvironmentId(environmentId), + ]); + + if (!session) { + throw new Error("Session not found"); + } if (!product) { throw new Error("Product not found"); @@ -16,6 +26,11 @@ export default async function SurveyTemplatesPage({ params }) { } return ( - + ); } diff --git a/apps/web/app/lib/members.ts b/apps/web/app/lib/members.ts deleted file mode 100644 index a48a1cac9e..0000000000 --- a/apps/web/app/lib/members.ts +++ /dev/null @@ -1,113 +0,0 @@ -export const updateMemberRole = async (teamId: string, userId: string, role: string) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/members/${userId}/`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ role }), - }); - return result.status === 200; - } catch (error) { - console.error(error); - return false; - } -}; - -export const transferOwnership = async (teamId: string, userId: string) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/transfer-ownership/`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ userId }), - }); - return result.status === 200; - } catch (error) { - console.error(error); - return false; - } -}; - -export const removeMember = async (teamId: string, userId: string) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/members/${userId}/`, { - method: "DELETE", - headers: { "Content-Type": "application/json" }, - }); - return result.status === 200; - } catch (error) { - console.error(error); - return false; - } -}; - -// update invitee's role -export const updateInviteeRole = async (teamId: string, inviteId: string, role: string) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/invite/${inviteId}/`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ role }), - }); - return result.status === 200; - } catch (error) { - console.error(error); - return false; - } -}; - -export const deleteInvite = async (teamId: string, inviteId: string) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/invite/${inviteId}/`, { - method: "DELETE", - headers: { "Content-Type": "application/json" }, - }); - return result.status === 200; - } catch (error) { - console.error(error); - return false; - } -}; - -export const addMember = async (teamId: string, data: { name: string; email: string }) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/invite/`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(data), - }); - return result.status === 201; - } catch (error) { - console.error(error); - return false; - } -}; - -export const resendInvite = async (teamId: string, inviteId: string) => { - try { - const result = await fetch(`/api/v1/teams/${teamId}/invite/${inviteId}`, { - method: "PUT", - headers: { "Content-Type": "application/json" }, - }); - return result.status === 200; - } catch (error) { - console.error(error); - return false; - } -}; - -export const shareInvite = async (teamId: string, inviteId: string) => { - try { - const res = await fetch(`/api/v1/teams/${teamId}/invite/${inviteId}`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - }); - - if (res.status !== 200) { - const json = await res.json(); - throw Error(json.message); - } - return res.json(); - } catch (error) { - console.error(error); - throw Error(`shareInvite: unable to get invite link: ${error.message}`); - } -}; diff --git a/apps/web/app/lib/profile.ts b/apps/web/app/lib/profile.ts deleted file mode 100644 index 05e3e0e869..0000000000 --- a/apps/web/app/lib/profile.ts +++ /dev/null @@ -1,26 +0,0 @@ -import useSWR from "swr"; -import { fetcher } from "@formbricks/lib/fetcher"; - -export const useProfile = () => { - const { data, isLoading, error, mutate, isValidating } = useSWR(`/api/v1/users/me/`, fetcher); - - return { - profile: data, - isLoadingProfile: isLoading, - isErrorProfile: error, - isValidatingProfile: isValidating, - mutateProfile: mutate, - }; -}; - -export const updateProfile = async (profile) => { - try { - await fetch(`/api/v1/users/me/`, { - method: "PUT", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(profile), - }); - } catch (error) { - console.error(error); - } -}; diff --git a/apps/web/app/lib/responseNotes/responsesNotes.ts b/apps/web/app/lib/responseNotes/responsesNotes.ts deleted file mode 100644 index b436b327b0..0000000000 --- a/apps/web/app/lib/responseNotes/responsesNotes.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const addResponseNote = async ( - environmentId: string, - surveyId: string, - responseId: string, - text: string -) => { - try { - const res = await fetch( - `/api/v1/environments/${environmentId}/surveys/${surveyId}/responses/${responseId}/responsesNotes`, - { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(text), - } - ); - return await res.json(); - } catch (error) { - console.error(error); - throw Error(`createResponseNote: unable to create responseNote: ${error.message}`); - } -}; diff --git a/apps/web/app/lib/utils.ts b/apps/web/app/lib/utils.ts index b6a0d2945e..4c64c91cd7 100644 --- a/apps/web/app/lib/utils.ts +++ b/apps/web/app/lib/utils.ts @@ -27,13 +27,6 @@ export const truncateMiddle = (str: string, length: number) => { return str; }; -export const scrollToTop = () => { - window.scrollTo({ - top: 0, - behavior: "smooth", - }); -}; - export function isLight(color) { let r, g, b; if (color.length === 4) { @@ -48,33 +41,6 @@ export function isLight(color) { return r * 0.299 + g * 0.587 + b * 0.114 > 128; } -const shuffle = (array: any[]) => { - for (let i = 0; i < array.length; i++) { - const j = Math.floor(Math.random() * (i + 1)); - [array[i], array[j]] = [array[j], array[i]]; - } -}; - -export const shuffleArray = (array: any[], shuffleOption: string | undefined) => { - const arrayCopy = [...array]; - const otherIndex = arrayCopy.findIndex((element) => element.id === "other"); - const otherElement = otherIndex !== -1 ? arrayCopy.splice(otherIndex, 1)[0] : null; - - if (shuffleOption === "all") { - shuffle(arrayCopy); - } else if (shuffleOption === "exceptLast") { - const lastElement = arrayCopy.pop(); - shuffle(arrayCopy); - arrayCopy.push(lastElement); - } - - if (otherElement) { - arrayCopy.push(otherElement); - } - - return arrayCopy; -}; - export enum MEMBERSHIP_ROLES { OWNER = "owner", ADMIN = "admin", diff --git a/apps/web/package.json b/apps/web/package.json index f54c9692c6..82787cf998 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -50,7 +50,6 @@ "react-hook-form": "^7.47.0", "react-hot-toast": "^2.4.1", "react-icons": "^4.11.0", - "swr": "^2.2.4", "ua-parser-js": "^1.0.36", "xlsx": "^0.18.5" }, diff --git a/packages/lib/profile/service.ts b/packages/lib/profile/service.ts index 33bbd717d4..1c17eb6e94 100644 --- a/packages/lib/profile/service.ts +++ b/packages/lib/profile/service.ts @@ -26,6 +26,7 @@ const responseSelection = { onboardingCompleted: true, twoFactorEnabled: true, identityProvider: true, + objective: true, }; export const getProfileCacheTag = (userId: string): string => `profiles-${userId}`; diff --git a/packages/types/profile.ts b/packages/types/profile.ts index 8611c27553..406be81da8 100644 --- a/packages/types/profile.ts +++ b/packages/types/profile.ts @@ -22,6 +22,7 @@ export const ZProfile = z.object({ createdAt: z.date(), updatedAt: z.date(), onboardingCompleted: z.boolean(), + objective: ZProfileObjective.nullable(), }); export type TProfile = z.infer; @@ -31,7 +32,7 @@ export const ZProfileUpdateInput = z.object({ email: z.string().optional(), onboardingCompleted: z.boolean().optional(), role: ZRole.optional(), - objective: ZProfileObjective.optional(), + objective: ZProfileObjective.nullish(), }); export type TProfileUpdateInput = z.infer; @@ -41,7 +42,7 @@ export const ZProfileCreateInput = z.object({ email: z.string(), onboardingCompleted: z.boolean().optional(), role: ZRole.optional(), - objective: ZProfileObjective.optional(), + objective: ZProfileObjective.nullish(), }); export type TProfileCreateInput = z.infer; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a6ec30f19..de518f044e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -398,9 +398,6 @@ importers: react-icons: specifier: ^4.11.0 version: 4.11.0(react@18.2.0) - swr: - specifier: ^2.2.4 - version: 2.2.4(react@18.2.0) ua-parser-js: specifier: ^1.0.36 version: 1.0.36 @@ -21461,16 +21458,6 @@ packages: es6-symbol: 3.1.3 dev: true - /swr@2.2.4(react@18.2.0): - resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} - peerDependencies: - react: ^16.11.0 || ^17.0.0 || ^18.0.0 - dependencies: - client-only: 0.0.1 - react: 18.2.0 - use-sync-external-store: 1.2.0(react@18.2.0) - dev: false - /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true