From b950348f0676c28bea38ec3d82d7bc458511c19d Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Fri, 9 Aug 2024 04:51:57 +0200 Subject: [PATCH 1/6] refactor: redirect to error and fetch per guild --- .../(marketing)/profile/[username]/page.tsx | 9 +-- .../profile/_components/EditContributions.tsx | 65 ++++++++----------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/src/app/(marketing)/profile/[username]/page.tsx b/src/app/(marketing)/profile/[username]/page.tsx index 0d19f6e673..c06199516e 100644 --- a/src/app/(marketing)/profile/[username]/page.tsx +++ b/src/app/(marketing)/profile/[username]/page.tsx @@ -10,7 +10,7 @@ import { SWRProvider } from "@/components/SWRProvider" import { Anchor } from "@/components/ui/Anchor" import { Guild, Role, Schemas } from "@guildxyz/types" import { ArrowRight } from "@phosphor-icons/react/dist/ssr" -import { notFound } from "next/navigation" +import { notFound, redirect } from "next/navigation" import { Profile } from "../_components/Profile" // TODO: use env var for this url when it is changed to this value. @@ -30,9 +30,10 @@ const fetchPublicProfileData = async ({ username }: { username: string }) => { revalidate: 600, }, }) - if (profileResponse.status === 404) { - notFound() - } + + if (profileResponse.status === 404) notFound() + if (!profileResponse.ok) redirect("/error") + const profile = (await profileResponse.json()) as Schemas["Profile"] const contributions = await ssrFetcher( contributionsRequest, diff --git a/src/app/(marketing)/profile/_components/EditContributions.tsx b/src/app/(marketing)/profile/_components/EditContributions.tsx index 1a5b7b8a79..cbc1617196 100644 --- a/src/app/(marketing)/profile/_components/EditContributions.tsx +++ b/src/app/(marketing)/profile/_components/EditContributions.tsx @@ -29,7 +29,6 @@ import { AvatarFallback } from "@radix-ui/react-avatar" import { DialogDescription } from "@radix-ui/react-dialog" import { useState } from "react" import useSWRImmutable from "swr/immutable" -import fetcher from "utils/fetcher" import { useContribution } from "../_hooks/useContribution" import { useCreateContribution } from "../_hooks/useCreateContribution" import { useDeleteContribution } from "../_hooks/useDeleteContribution" @@ -37,23 +36,11 @@ import { useMemberships } from "../_hooks/useMemberships" import { useUpdateContribution } from "../_hooks/useUpdateContribution" import { CardWithGuildLabel } from "./CardWithGuildLabel" -const guildFetcher = (urls: string[]) => { - return Promise.all(urls.map((url) => fetcher(url) as Promise)) -} -const useYourVerifiedGuild = () => { - const yourGuilds = useYourGuilds() - const requests = yourGuilds.data - ? yourGuilds.data.map((guild) => `/v2/guilds/${guild.id}`) - : null - return { guilds: useSWRImmutable(requests, guildFetcher), baseGuilds: yourGuilds } -} - const EditContributionCard = ({ contribution, }: { contribution: Schemas["Contribution"] }) => { const { data: guild } = useSWRImmutable( - `/v2/guilds/${contribution.guildId}`, - fetcher + `/v2/guilds/${contribution.guildId}` ) const memberships = useMemberships() const editContribution = useUpdateContribution({ contributionId: contribution.id }) @@ -107,17 +94,8 @@ export const EditContributions = () => { const [roleId, setRoleId] = useState("") const { toast } = useToast() - const { - guilds: { data: guildData }, - baseGuilds, - } = useYourVerifiedGuild() - const guilds = - guildData && - baseGuilds.data?.reduce( - (acc, curr, i) => - curr.tags.includes("VERIFIED") ? [...acc, guildData[i]] : acc, - [] - ) + const { data: baseGuilds } = useYourGuilds() + const guilds = baseGuilds?.filter(({ tags }) => tags.includes("VERIFIED")) const roleIds = memberships.data?.find( (membership) => membership.guildId.toString() === guildId @@ -165,20 +143,7 @@ export const EditContributions = () => { {guilds?.map((data) => ( - -
- - - - - {data.name} -
-
+ ))}
@@ -233,6 +198,28 @@ export const EditContributions = () => { ) } + +const GuildSelectItem = ({ guildId }: Pick) => { + const { data } = useSWRImmutable(`/v2/guilds/${guildId}`) + if (!data) return + return ( + +
+ + + + + {data.name} +
+
+ ) +} + const RoleSelectItem = ({ roleId, guildId, From 115a6952b02a6f2968b18f7661af385e84f9ffa1 Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Fri, 9 Aug 2024 07:31:47 +0200 Subject: [PATCH 2/6] feat: add optimistic update to contributions --- .../profile/_hooks/useCreateContribution.tsx | 36 ++++++++++++++----- .../profile/_hooks/useDeleteContribution.tsx | 24 ++++++++----- src/hooks/useSubmit/types.ts | 1 + src/hooks/useSubmit/useSubmit.ts | 13 +++++-- 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx b/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx index abfbc22ee2..b15e1163f4 100644 --- a/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx @@ -11,7 +11,7 @@ export type EditProfilePayload = Schemas["ContributionUpdate"] export const useCreateContribution = () => { const { toast } = useToast() const { data: profile } = useProfile() - const contribution = useContribution() + const contributions = useContribution() const update = async (signedValidation: SignedValidation) => { return fetcher( @@ -24,16 +24,34 @@ export const useCreateContribution = () => { } const submitWithSign = useSubmitWithSign(update, { - onSuccess: (response) => { - contribution.mutate( - (prev) => { - // WARNING: should we validate here? - if (!prev) return - prev.push(response) - return prev + onOptimistic: (response, payload) => { + if (!profile?.userId) return + contributions.mutate( + async () => { + if (!contributions.data) return + const contribution = await response + contributions.data[contributions.data.findIndex(({ id }) => id === -1)] = + contribution + // contributions.data.push(await response) + return contributions.data }, - { revalidate: false } + { + revalidate: false, + rollbackOnError: true, + optimisticData: () => { + const fakeContribution: Schemas["Contribution"] = { + ...(payload as EditProfilePayload), + id: -1, + profileId: profile.userId, + } + if (!contributions.data) return [fakeContribution] + contributions.data.push(fakeContribution) + return contributions.data + }, + } ) + }, + onSuccess: (response) => { revalidateContribution() toast({ variant: "success", diff --git a/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx b/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx index f69753505e..797c9318ec 100644 --- a/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx @@ -11,7 +11,7 @@ export const useDeleteContribution = ({ }: { contributionId: Schemas["Contribution"]["id"] }) => { const { toast } = useToast() const { data: profile } = useProfile() - const contribution = useContribution() + const contributions = useContribution() const update = async (signedValidation: SignedValidation) => { return fetcher( @@ -24,15 +24,23 @@ export const useDeleteContribution = ({ } const submitWithSign = useSubmitWithSign(update, { - onSuccess: () => { - contribution.mutate( - (prev) => { - if (!prev || !contribution.data) return - // WARNING: should we validate here? - return prev.filter((p) => p.id !== contributionId) + onOptimistic: (response) => { + contributions.mutate( + async () => { + await response + return contributions.data?.filter((p) => p.id !== contributionId) }, - { revalidate: false } + { + revalidate: false, + rollbackOnError: true, + optimisticData: () => { + if (!contributions.data) return [] + return contributions.data.filter((p) => p.id !== contributionId) + }, + } ) + }, + onSuccess: () => { revalidateContribution() toast({ variant: "success", diff --git a/src/hooks/useSubmit/types.ts b/src/hooks/useSubmit/types.ts index cffa07fd2a..6da8497725 100644 --- a/src/hooks/useSubmit/types.ts +++ b/src/hooks/useSubmit/types.ts @@ -40,6 +40,7 @@ export type MessageParams = { export type UseSubmitOptions = { onSuccess?: (response: ResponseType) => void onError?: (error: any) => void + onOptimistic?: (response: Promise, payload: any) => void // Use catefully! If this is set to true, a .onSubmit() call can reject! allowThrow?: boolean diff --git a/src/hooks/useSubmit/useSubmit.ts b/src/hooks/useSubmit/useSubmit.ts index 048e1c2007..575acc7523 100644 --- a/src/hooks/useSubmit/useSubmit.ts +++ b/src/hooks/useSubmit/useSubmit.ts @@ -21,7 +21,12 @@ type FetcherFunction = ({ const useSubmit = ( fetch: (data?: DataType) => Promise, - { onSuccess, onError, allowThrow }: UseSubmitOptions = {} + { + onSuccess, + onError, + allowThrow, + onOptimistic, + }: UseSubmitOptions = {} ) => { const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(undefined) @@ -31,7 +36,9 @@ const useSubmit = ( (data?: DataType): Promise => { setIsLoading(true) setError(undefined) - return fetch(data) + const response = fetch(data) + onOptimistic?.(response, data) + return response .then((d) => { onSuccess?.(d) setResponse(d) @@ -47,7 +54,7 @@ const useSubmit = ( }) .finally(() => setIsLoading(false)) }, - [allowThrow, fetch, onError, onSuccess] + [allowThrow, fetch, onError, onSuccess, onOptimistic] ) return { From efde96a6750cfa1dba3e3f60de98166ada077196 Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Fri, 9 Aug 2024 08:08:03 +0200 Subject: [PATCH 3/6] feat: finish update contribution and polish --- .../profile/_components/EditContributions.tsx | 4 +- .../profile/_components/Profile.tsx | 4 +- ...eContribution.tsx => useContributions.tsx} | 2 +- .../profile/_hooks/useCreateContribution.tsx | 25 +++++------- .../profile/_hooks/useDeleteContribution.tsx | 8 +--- .../profile/_hooks/useUpdateContribution.tsx | 40 +++++++++++-------- 6 files changed, 41 insertions(+), 42 deletions(-) rename src/app/(marketing)/profile/_hooks/{useContribution.tsx => useContributions.tsx} (88%) diff --git a/src/app/(marketing)/profile/_components/EditContributions.tsx b/src/app/(marketing)/profile/_components/EditContributions.tsx index cbc1617196..e428d5c431 100644 --- a/src/app/(marketing)/profile/_components/EditContributions.tsx +++ b/src/app/(marketing)/profile/_components/EditContributions.tsx @@ -29,7 +29,7 @@ import { AvatarFallback } from "@radix-ui/react-avatar" import { DialogDescription } from "@radix-ui/react-dialog" import { useState } from "react" import useSWRImmutable from "swr/immutable" -import { useContribution } from "../_hooks/useContribution" +import { useContributions } from "../_hooks/useContributions" import { useCreateContribution } from "../_hooks/useCreateContribution" import { useDeleteContribution } from "../_hooks/useDeleteContribution" import { useMemberships } from "../_hooks/useMemberships" @@ -88,7 +88,7 @@ const EditContributionCard = ({ } export const EditContributions = () => { - const contributions = useContribution() + const contributions = useContributions() const memberships = useMemberships() const [guildId, setGuildId] = useState("") const [roleId, setRoleId] = useState("") diff --git a/src/app/(marketing)/profile/_components/Profile.tsx b/src/app/(marketing)/profile/_components/Profile.tsx index 99510c1cac..b626107250 100644 --- a/src/app/(marketing)/profile/_components/Profile.tsx +++ b/src/app/(marketing)/profile/_components/Profile.tsx @@ -11,13 +11,13 @@ import { EditProfile } from "../_components/EditProfile" import { OperatedGuildCard } from "../_components/OperatedGuildCard" import { ProfileOwnerGuard } from "../_components/ProfileOwnerGuard" import { RecentActivity } from "../_components/RecentActivity" -import { useContribution } from "../_hooks/useContribution" +import { useContributions } from "../_hooks/useContributions" import { useProfile } from "../_hooks/useProfile" import { ProfileSkeleton } from "./ProfileSkeleton" export const Profile = () => { const { data: profile } = useProfile() - const { data: contributions } = useContribution() + const { data: contributions } = useContributions() if (!profile || !contributions) return diff --git a/src/app/(marketing)/profile/_hooks/useContribution.tsx b/src/app/(marketing)/profile/_hooks/useContributions.tsx similarity index 88% rename from src/app/(marketing)/profile/_hooks/useContribution.tsx rename to src/app/(marketing)/profile/_hooks/useContributions.tsx index 88c4c01317..6c51947abf 100644 --- a/src/app/(marketing)/profile/_hooks/useContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useContributions.tsx @@ -2,7 +2,7 @@ import { Schemas } from "@guildxyz/types" import useSWRImmutable from "swr/immutable" import { useProfile } from "./useProfile" -export const useContribution = () => { +export const useContributions = () => { const { data: profileData } = useProfile() return useSWRImmutable( profileData ? `/v2/profiles/${profileData.username}/contributions` : null diff --git a/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx b/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx index b15e1163f4..f9c304f3ab 100644 --- a/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx @@ -3,15 +3,13 @@ import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import fetcher from "utils/fetcher" import { revalidateContribution } from "../_server_actions/revalidateContribution" -import { useContribution } from "./useContribution" +import { useContributions } from "./useContributions" import { useProfile } from "./useProfile" -export type EditProfilePayload = Schemas["ContributionUpdate"] - export const useCreateContribution = () => { const { toast } = useToast() const { data: profile } = useProfile() - const contributions = useContribution() + const contributions = useContributions() const update = async (signedValidation: SignedValidation) => { return fetcher( @@ -30,17 +28,18 @@ export const useCreateContribution = () => { async () => { if (!contributions.data) return const contribution = await response - contributions.data[contributions.data.findIndex(({ id }) => id === -1)] = - contribution - // contributions.data.push(await response) - return contributions.data + contributions.data[ + contributions.data.findLastIndex(({ id }) => id === -1) + ] = contribution + return contributions.data.filter(({ id }) => id !== -1) }, { revalidate: false, rollbackOnError: true, optimisticData: () => { + // @ts-expect-error: incorrect types coming from lib const fakeContribution: Schemas["Contribution"] = { - ...(payload as EditProfilePayload), + ...(payload as Schemas["ContributionUpdate"]), id: -1, profileId: profile.userId, } @@ -51,12 +50,8 @@ export const useCreateContribution = () => { } ) }, - onSuccess: (response) => { + onSuccess: () => { revalidateContribution() - toast({ - variant: "success", - title: "Successfully created contribution", - }) }, onError: (response) => { toast({ @@ -68,7 +63,7 @@ export const useCreateContribution = () => { }) return { ...submitWithSign, - onSubmit: (payload: EditProfilePayload) => + onSubmit: (payload: Schemas["ContributionUpdate"]) => profile && submitWithSign.onSubmit(payload), } } diff --git a/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx b/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx index 797c9318ec..1fe7277164 100644 --- a/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx @@ -3,7 +3,7 @@ import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import fetcher from "utils/fetcher" import { revalidateContribution } from "../_server_actions/revalidateContribution" -import { useContribution } from "./useContribution" +import { useContributions } from "./useContributions" import { useProfile } from "./useProfile" export const useDeleteContribution = ({ @@ -11,7 +11,7 @@ export const useDeleteContribution = ({ }: { contributionId: Schemas["Contribution"]["id"] }) => { const { toast } = useToast() const { data: profile } = useProfile() - const contributions = useContribution() + const contributions = useContributions() const update = async (signedValidation: SignedValidation) => { return fetcher( @@ -42,10 +42,6 @@ export const useDeleteContribution = ({ }, onSuccess: () => { revalidateContribution() - toast({ - variant: "success", - title: "Successfully deleted contribution", - }) }, onError: (response) => { toast({ diff --git a/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx b/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx index febe464054..b82f881f99 100644 --- a/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx @@ -3,7 +3,7 @@ import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import fetcher from "utils/fetcher" import { revalidateContribution } from "../_server_actions/revalidateContribution" -import { useContribution } from "./useContribution" +import { useContributions } from "./useContributions" import { useProfile } from "./useProfile" export const useUpdateContribution = ({ @@ -11,7 +11,7 @@ export const useUpdateContribution = ({ }: { contributionId: Schemas["Contribution"]["id"] }) => { const { toast } = useToast() const { data: profile } = useProfile() - const contribution = useContribution() + const contributions = useContributions() const update = async (signedValidation: SignedValidation) => { return fetcher( @@ -24,24 +24,32 @@ export const useUpdateContribution = ({ } const submitWithSign = useSubmitWithSign(update, { - onSuccess: (response) => { - contribution.mutate( - (prev) => { - if (!prev || !contribution.data) return - // WARNING: should we validate here? - return prev.map((p) => - p.id === (contribution.data as unknown as Schemas["Contribution"]).id - ? response - : p + onOptimistic: (response, payload) => { + if (!profile?.userId) return + contributions.mutate( + async () => { + if (!contributions.data) return + const contribution = await response + return contributions.data.map((data) => + data.id === contributionId ? contribution : data ) }, - { revalidate: false } + { + revalidate: false, + rollbackOnError: true, + optimisticData: () => { + if (!contributions.data) return [] + return contributions.data.map((data) => + data.id === contributionId + ? { ...data, ...(payload as Schemas["Contribution"]) } + : data + ) + }, + } ) + }, + onSuccess: () => { revalidateContribution() - toast({ - variant: "success", - title: "Successfully updated contribution", - }) }, onError: (response) => { toast({ From 8ca39f1823fceff035f76ccb8f9323763025f6da Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Fri, 9 Aug 2024 08:24:17 +0200 Subject: [PATCH 4/6] feat: add optimistic update to profile --- .../profile/_hooks/useUpdateProfile.ts | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts b/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts index 8da9a9a059..c5205b80e5 100644 --- a/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts +++ b/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts @@ -5,12 +5,13 @@ import { useParams, useRouter } from "next/navigation" import fetcher from "utils/fetcher" import { revalidateProfile } from "../_server_actions/revalidateProfile" import { useProfile } from "./useProfile" +import { revalidateContribution } from "../_server_actions/revalidateContribution" export const useUpdateProfile = () => { const { toast } = useToast() const router = useRouter() const params = useParams<{ username: string }>() - const { mutate } = useProfile() + const { mutate, data: profile } = useProfile() const updateProfile = async (signedValidation: SignedValidation) => { return fetcher(`/v2/profiles/${params?.username}`, { @@ -20,18 +21,21 @@ export const useUpdateProfile = () => { } const submitWithSign = useSubmitWithSign(updateProfile, { - onSuccess: (response) => { - console.log("onSuccess", response) - router.replace(`/profile/${response.username}`) - mutate(() => response, { revalidate: false }) - revalidateProfile() - toast({ - variant: "success", - title: "Successfully updated profile", + onOptimistic: (response, payload) => { + mutate(() => response, { + revalidate: false, + rollbackOnError: true, + optimisticData: () => payload, }) }, + onSuccess: async (response) => { + await revalidateProfile() + if (profile?.username !== response.username) { + await revalidateContribution() + router.replace(`/profile/${response.username}`) + } + }, onError: (response) => { - console.log("onError", response) toast({ variant: "error", title: "Failed to update profile", From 60020c3f171f1e98f2dfbc4e4cdc992355034679 Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Fri, 9 Aug 2024 08:32:05 +0200 Subject: [PATCH 5/6] chore: rename revalidateContribution and fix type error --- src/app/(marketing)/profile/_hooks/useCreateContribution.tsx | 4 ++-- src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx | 4 ++-- src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx | 4 ++-- src/app/(marketing)/profile/_hooks/useUpdateProfile.ts | 4 ++-- .../{revalidateContribution.ts => revalidateContributions.ts} | 2 +- src/hooks/useSubmit/useSubmit.ts | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) rename src/app/(marketing)/profile/_server_actions/{revalidateContribution.ts => revalidateContributions.ts} (65%) diff --git a/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx b/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx index f9c304f3ab..e7d840da46 100644 --- a/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useCreateContribution.tsx @@ -2,7 +2,7 @@ import { useToast } from "@/components/ui/hooks/useToast" import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import fetcher from "utils/fetcher" -import { revalidateContribution } from "../_server_actions/revalidateContribution" +import { revalidateContributions } from "../_server_actions/revalidateContributions" import { useContributions } from "./useContributions" import { useProfile } from "./useProfile" @@ -51,7 +51,7 @@ export const useCreateContribution = () => { ) }, onSuccess: () => { - revalidateContribution() + revalidateContributions() }, onError: (response) => { toast({ diff --git a/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx b/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx index 1fe7277164..9a09b2e75e 100644 --- a/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useDeleteContribution.tsx @@ -2,7 +2,7 @@ import { useToast } from "@/components/ui/hooks/useToast" import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import fetcher from "utils/fetcher" -import { revalidateContribution } from "../_server_actions/revalidateContribution" +import { revalidateContributions } from "../_server_actions/revalidateContributions" import { useContributions } from "./useContributions" import { useProfile } from "./useProfile" @@ -41,7 +41,7 @@ export const useDeleteContribution = ({ ) }, onSuccess: () => { - revalidateContribution() + revalidateContributions() }, onError: (response) => { toast({ diff --git a/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx b/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx index b82f881f99..cfc847d9d8 100644 --- a/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx +++ b/src/app/(marketing)/profile/_hooks/useUpdateContribution.tsx @@ -2,7 +2,7 @@ import { useToast } from "@/components/ui/hooks/useToast" import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import fetcher from "utils/fetcher" -import { revalidateContribution } from "../_server_actions/revalidateContribution" +import { revalidateContributions } from "../_server_actions/revalidateContributions" import { useContributions } from "./useContributions" import { useProfile } from "./useProfile" @@ -49,7 +49,7 @@ export const useUpdateContribution = ({ ) }, onSuccess: () => { - revalidateContribution() + revalidateContributions() }, onError: (response) => { toast({ diff --git a/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts b/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts index c5205b80e5..fcd54d6263 100644 --- a/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts +++ b/src/app/(marketing)/profile/_hooks/useUpdateProfile.ts @@ -3,9 +3,9 @@ import { Schemas } from "@guildxyz/types" import { SignedValidation, useSubmitWithSign } from "hooks/useSubmit" import { useParams, useRouter } from "next/navigation" import fetcher from "utils/fetcher" +import { revalidateContributions } from "../_server_actions/revalidateContributions" import { revalidateProfile } from "../_server_actions/revalidateProfile" import { useProfile } from "./useProfile" -import { revalidateContribution } from "../_server_actions/revalidateContribution" export const useUpdateProfile = () => { const { toast } = useToast() @@ -31,7 +31,7 @@ export const useUpdateProfile = () => { onSuccess: async (response) => { await revalidateProfile() if (profile?.username !== response.username) { - await revalidateContribution() + await revalidateContributions() router.replace(`/profile/${response.username}`) } }, diff --git a/src/app/(marketing)/profile/_server_actions/revalidateContribution.ts b/src/app/(marketing)/profile/_server_actions/revalidateContributions.ts similarity index 65% rename from src/app/(marketing)/profile/_server_actions/revalidateContribution.ts rename to src/app/(marketing)/profile/_server_actions/revalidateContributions.ts index fa10ae1ed6..cbf800b1f7 100644 --- a/src/app/(marketing)/profile/_server_actions/revalidateContribution.ts +++ b/src/app/(marketing)/profile/_server_actions/revalidateContributions.ts @@ -2,6 +2,6 @@ import { revalidateTag } from "next/cache" -export async function revalidateContribution() { +export async function revalidateContributions() { revalidateTag("contributions") } diff --git a/src/hooks/useSubmit/useSubmit.ts b/src/hooks/useSubmit/useSubmit.ts index 575acc7523..75a5f630bb 100644 --- a/src/hooks/useSubmit/useSubmit.ts +++ b/src/hooks/useSubmit/useSubmit.ts @@ -26,7 +26,7 @@ const useSubmit = ( onError, allowThrow, onOptimistic, - }: UseSubmitOptions = {} + }: UseSubmitOptions = {} ) => { const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(undefined) From 12ae70cdc1aed9641776fe2032508b8400604aa8 Mon Sep 17 00:00:00 2001 From: Dominik Stumpf Date: Fri, 9 Aug 2024 09:04:36 +0200 Subject: [PATCH 6/6] feat: memoize profile guard --- .../(marketing)/profile/_components/ProfileOwnerGuard.tsx | 8 +++++--- src/hooks/useSetKeyPair.ts | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/(marketing)/profile/_components/ProfileOwnerGuard.tsx b/src/app/(marketing)/profile/_components/ProfileOwnerGuard.tsx index 6de4e15b1e..1788c4f967 100644 --- a/src/app/(marketing)/profile/_components/ProfileOwnerGuard.tsx +++ b/src/app/(marketing)/profile/_components/ProfileOwnerGuard.tsx @@ -1,14 +1,16 @@ "use client" import { useUserPublic } from "@/hooks/useUserPublic" -import { PropsWithChildren } from "react" +import { PropsWithChildren, useMemo } from "react" import { useProfile } from "../_hooks/useProfile" export const ProfileOwnerGuard = ({ children }: PropsWithChildren) => { const { data: profile } = useProfile() const { id: publicUserId } = useUserPublic() - const isProfileOwner = !!profile?.userId && publicUserId === profile.userId - + const isProfileOwner = useMemo( + () => !!profile?.userId && publicUserId === profile.userId, + [publicUserId] + ) if (!isProfileOwner) return return children } diff --git a/src/hooks/useSetKeyPair.ts b/src/hooks/useSetKeyPair.ts index b1ebf9503f..4b2cc6b55e 100644 --- a/src/hooks/useSetKeyPair.ts +++ b/src/hooks/useSetKeyPair.ts @@ -94,6 +94,7 @@ const useSetKeyPair = (submitOptions?: UseSubmitOptions) => { const recaptcha = useAtomValue(recaptchaAtom) const setSubmitResponse = useSubmit( + // @ts-ignore async ({ signProps, }: { @@ -175,6 +176,7 @@ const useSetKeyPair = (submitOptions?: UseSubmitOptions) => { return { keyPair: generatedKeys, user: userProfile } }, + // @ts-ignore { ...submitOptions, onError: (error) => {