-
Notifications
You must be signed in to change notification settings - Fork 10k
perf: server-fetch data for all pages in /settings/my-account #20712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a8db37a
0f78fff
6149ea5
f9c0549
8111869
d4bde99
e8f24c2
f463b60
866000d
d801a26
58fc67a
f0214f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
"use server"; | ||
|
||
import { revalidatePath } from "next/cache"; | ||
|
||
export async function revalidateSettingsAppearance() { | ||
revalidatePath("/settings/my-account/appearance"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { SkeletonLoader } from "~/settings/my-account/appearance-skeleton"; | ||
|
||
export default function Loading() { | ||
return <SkeletonLoader />; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { CalendarListContainerSkeletonLoader } from "@components/apps/CalendarListContainer"; | ||
|
||
export default function Loading() { | ||
return <CalendarListContainerSkeletonLoader />; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
"use server"; | ||
|
||
import { revalidatePath } from "next/cache"; | ||
|
||
export async function revalidateSettingsGeneral() { | ||
revalidatePath("/settings/my-account/general"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { SkeletonLoader } from "~/settings/my-account/general-skeleton"; | ||
|
||
export default function Loading() { | ||
return <SkeletonLoader />; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { SkeletonLoader } from "~/settings/my-account/profile-skeleton"; | ||
|
||
export default function Loading() { | ||
return <SkeletonLoader />; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import { createRouterCaller } from "app/_trpc/context"; | ||
import { _generateMetadata } from "app/_utils"; | ||
import { getTranslate } from "app/_utils"; | ||
import { redirect } from "next/navigation"; | ||
|
||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; | ||
import { APP_NAME } from "@calcom/lib/constants"; | ||
import { meRouter } from "@calcom/trpc/server/routers/viewer/me/_router"; | ||
|
||
import ProfileView from "~/settings/my-account/profile-view"; | ||
|
||
|
@@ -16,16 +16,13 @@ export const generateMetadata = async () => | |
); | ||
|
||
const Page = async () => { | ||
const t = await getTranslate(); | ||
const meCaller = await createRouterCaller(meRouter); | ||
const user = await meCaller.get({ includePasswordAdded: true }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The get() call uses an object with includePasswordAdded: true, which may result in overfetching if the implementation uses Prisma's include instead of select. Per project guidelines, always use select to fetch only required fields and avoid unnecessary data exposure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The get() call uses an object with includePasswordAdded: true, which may result in overfetching if the implementation uses Prisma's include instead of select. Per project guidelines, always use select to fetch only required fields and avoid unnecessary data exposure. |
||
if (!user) { | ||
redirect("/auth/login"); | ||
} | ||
|
||
return ( | ||
<SettingsHeader | ||
title={t("profile")} | ||
description={t("profile_description", { appName: APP_NAME })} | ||
borderInShellHeader={true}> | ||
<ProfileView /> | ||
</SettingsHeader> | ||
); | ||
return <ProfileView user={user} />; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directly passing the user object as a prop may result in prop drilling if ProfileView passes it further down. Prefer composition or context for user data to avoid deep prop drilling, per project guidelines. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directly passing the user object as a prop may result in prop drilling if ProfileView passes it further down. Prefer composition or context for user data to avoid deep prop drilling, per project guidelines. |
||
}; | ||
|
||
export default Page; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"use server"; | ||
|
||
import { revalidateTag, unstable_cache } from "next/cache"; | ||
|
||
import { NEXTJS_CACHE_TTL } from "@calcom/lib/constants"; | ||
import { MembershipRepository } from "@calcom/lib/server/repository/membership"; | ||
|
||
const CACHE_TAGS = { | ||
HAS_TEAM_PLAN: "MembershipRepository.findFirstAcceptedMembershipByUserId", | ||
} as const; | ||
|
||
export const getCachedHasTeamPlan = unstable_cache( | ||
async (userId: number) => { | ||
const hasTeamPlan = await MembershipRepository.findFirstAcceptedMembershipByUserId(userId); | ||
|
||
return { hasTeamPlan: !!hasTeamPlan }; | ||
}, | ||
["getCachedHasTeamPlan"], | ||
{ | ||
revalidate: NEXTJS_CACHE_TTL, | ||
tags: [CACHE_TAGS.HAS_TEAM_PLAN], | ||
} | ||
); | ||
|
||
export const revalidateHasTeamPlan = async () => { | ||
revalidateTag(CACHE_TAGS.HAS_TEAM_PLAN); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
"use server"; | ||
|
||
import { revalidatePath } from "next/cache"; | ||
|
||
export async function revalidateSettingsProfile() { | ||
revalidatePath("/settings/my-account/profile"); | ||
} | ||
|
||
export async function revalidateSettingsCalendars() { | ||
revalidatePath("/settings/my-account/calendars"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Component no longer uses SettingsHeader which affects UI consistency across settings pages