The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

improve guild data fetching

Luna 314c5bfd 15eb4e65

+86 -121
+86 -121
app/dashboard/[guildId]/layout.tsx
··· 8 8 import { Suspense, useEffect, useState } from "react"; 9 9 import { BiLogoYoutube } from "react-icons/bi"; 10 10 import { HiArrowNarrowLeft, HiChartBar, HiCode, HiCursorClick, HiEye, HiHome, HiShare, HiStar, HiUserAdd, HiUsers, HiViewGridAdd } from "react-icons/hi"; 11 + import { useQuery } from "react-query"; 11 12 12 13 import { guildStore } from "@/common/guilds"; 13 14 import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; ··· 15 16 import { ListTab } from "@/components/list"; 16 17 import { AddButton, ScreenMessage, SupportButton } from "@/components/screen-message"; 17 18 import { ServerButton } from "@/components/server-button"; 19 + import { cacheOptions, getData } from "@/lib/api"; 18 20 import SadWumpusPic from "@/public/sad-wumpus.gif"; 19 - import { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse, RouteErrorResponse } from "@/typings"; 21 + import { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse } from "@/typings"; 20 22 import { intl } from "@/utils/numbers"; 21 23 import { getCanonicalUrl } from "@/utils/urls"; 22 24 ··· 27 29 }) { 28 30 const cookies = useCookies(); 29 31 const params = useParams(); 30 - const hasSession = cookies.get("hasSession") === "true"; 32 + const path = usePathname(); 31 33 32 - if (!hasSession) redirect(`/login?callback=/dashboard/${params.guildId}`); 33 - 34 + const [error, setError] = useState<string>(); 35 + const [loaded, setLoaded] = useState<string[]>([]); 34 36 const guild = guildStore((g) => g); 35 37 36 - const [error, setError] = useState<string>(); 38 + const hasSession = cookies.get("hasSession") === "true"; 39 + const isDevMode = cookies.get("devTools") === "true"; 37 40 38 - const path = usePathname(); 41 + if (!hasSession) redirect(`/login?callback=/dashboard/${params.guildId}`); 39 42 40 - useEffect(() => { 43 + const url = `/guilds/${params.guildId}` as const; 41 44 42 - fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${params.guildId}`, { 43 - credentials: "include" 44 - }) 45 - .then(async (res) => { 46 - const response = await res.json() as ApiV1GuildsGetResponse; 47 - if (!response) return; 45 + const { data, isLoading } = useQuery( 46 + url, 47 + () => getData<ApiV1GuildsGetResponse>(url), 48 + { 49 + enabled: !!params.guildId, 50 + ...cacheOptions 51 + } 52 + ); 48 53 49 - switch (res.status) { 50 - case 200: { 51 - setError(undefined); 52 - guildStore.setState(response); 53 - break; 54 - } 55 - default: { 56 - guildStore.setState(undefined); 57 - setError((response as unknown as RouteErrorResponse).message); 58 - break; 59 - } 54 + useQuery( 55 + url + "/channels", 56 + () => getData<ApiV1GuildsChannelsGetResponse[]>(url + "/channels"), 57 + { 58 + enabled: !!guild?.id, 59 + onSettled: (d) => { 60 + if (!d||"message" in d) { 61 + setError(d?.message || "Failed to fetch channels."); 62 + return; 60 63 } 61 64 62 - }) 63 - .catch(() => { 64 - setError("Error while fetching guilds"); 65 - }); 65 + guildStore.setState({ 66 + ...guild, 67 + channels: d 68 + }); 66 69 67 - 68 - 69 - fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${params.guildId}/channels`, { 70 - credentials: "include" 71 - }) 72 - .then(async (res) => { 73 - const response = await res.json() as ApiV1GuildsChannelsGetResponse[]; 74 - if (!response) return; 70 + setLoaded((loaded) => [...loaded, "channels"]); 71 + }, 72 + ...cacheOptions 73 + } 74 + ); 75 75 76 - switch (res.status) { 77 - case 200: { 78 - guildStore.setState({ 79 - ...guild, 80 - channels: response 81 - }); 82 - break; 83 - } 84 - default: { 85 - guildStore.setState({ 86 - ...guild, 87 - channels: [] 88 - }); 89 - setError((response as unknown as RouteErrorResponse).message); 90 - break; 91 - } 76 + useQuery( 77 + url + "/roles", 78 + () => getData<ApiV1GuildsRolesGetResponse[]>(url + "/roles"), 79 + { 80 + enabled: !!guild?.id, 81 + onSettled: (d) => { 82 + if (!d||"message" in d) { 83 + setError(d?.message || "Failed to fetch roles."); 84 + return; 92 85 } 93 86 94 - }) 95 - .catch(() => { 96 - setError("Error while fetching channels"); 97 - }); 87 + guildStore.setState({ 88 + ...guild, 89 + roles: d 90 + }); 98 91 99 - fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${params.guildId}/roles`, { 100 - credentials: "include" 101 - }) 102 - .then(async (res) => { 103 - const response = await res.json() as ApiV1GuildsRolesGetResponse[]; 104 - if (!response) return; 92 + setLoaded((loaded) => [...loaded, "roles"]); 93 + }, 94 + ...cacheOptions 95 + } 96 + ); 105 97 106 - switch (res.status) { 107 - case 200: { 108 - guildStore.setState({ 109 - ...guild, 110 - roles: response 111 - }); 112 - break; 113 - } 114 - default: { 115 - guildStore.setState({ 116 - ...guild, 117 - roles: response 118 - }); 119 - setError((response as unknown as RouteErrorResponse).message); 120 - break; 121 - } 98 + useQuery( 99 + url + "/emojis", 100 + () => getData<ApiV1GuildsEmojisGetResponse[]>(url + "/emojis"), 101 + { 102 + enabled: !!guild?.id, 103 + onSettled: (d) => { 104 + if (!d||"message" in d) { 105 + setError(d?.message || "Failed to fetch emojis."); 106 + return; 122 107 } 123 108 124 - }) 125 - .catch(() => { 126 - setError("Error while fetching roles"); 127 - }); 109 + guildStore.setState({ 110 + ...guild, 111 + emojis: d 112 + }); 128 113 129 - fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${params.guildId}/emojis`, { 130 - credentials: "include" 131 - }) 132 - .then(async (res) => { 133 - const response = await res.json() as ApiV1GuildsEmojisGetResponse[]; 134 - if (!response) return; 114 + setLoaded((loaded) => [...loaded, "emojis"]); 115 + }, 116 + ...cacheOptions 117 + } 118 + ); 135 119 136 - switch (res.status) { 137 - case 200: { 120 + useEffect(() => { 121 + if (data && "message" in data) { 122 + setError(data?.message); 123 + return; 124 + } 138 125 139 - guildStore.setState({ 140 - ...guild, 141 - emojis: response 142 - }); 143 - break; 144 - } 145 - default: { 146 - 147 - guildStore.setState({ 148 - ...guild, 149 - emojis: response 150 - }); 151 - setError((response as unknown as RouteErrorResponse).message); 152 - break; 153 - } 154 - } 155 - 156 - }) 157 - .catch(() => { 158 - setError("Error while fetching roles"); 159 - }); 160 - 161 - }, []); 126 + guildStore.setState(data); 127 + }, [data]); 162 128 163 129 return ( 164 130 <div className="flex flex-col w-full"> ··· 174 140 > 175 141 Serverlist 176 142 </Button> 177 - {cookies.get("devTools") && 143 + {isDevMode && 178 144 <CopyToClipboardButton 179 - needsWait 180 145 text={getCanonicalUrl("leaderboard", params.guildId.toString())} 181 146 items={[ 182 147 { icon: <HiShare />, name: "Copy page url", description: "Creates a link to this specific page", text: getCanonicalUrl(...path.split("/").slice(1)) }, ··· 188 153 </div> 189 154 190 155 <div className="text-lg flex gap-5"> 191 - <Skeleton isLoaded={!!guild?.id} className="rounded-full h-14 w-14 ring-offset-[var(--background-rgb)] ring-2 ring-offset-2 ring-violet-400/40 shrink-0"> 156 + <Skeleton isLoaded={!isLoading} className="rounded-full h-14 w-14 ring-offset-[var(--background-rgb)] ring-2 ring-offset-2 ring-violet-400/40 shrink-0"> 192 157 <ImageReduceMotion 193 158 alt="this server" 194 159 className="rounded-full" ··· 197 162 /> 198 163 </Skeleton> 199 164 200 - {!guild?.id ? 165 + {isLoading ? 201 166 <div className="mt-1.5"> 202 167 <Skeleton className="rounded-xl w-32 h-6 mb-2" /> 203 168 <Skeleton className="rounded-xl w-10 h-3.5" /> ··· 253 218 } 254 219 ]} 255 220 url={`/dashboard/${params.guildId}`} 256 - disabled={!guild?.id || !!error} 221 + disabled={!guild || !!error} 257 222 /> 258 223 </Suspense> 259 224 260 225 {error ? 261 226 <ScreenMessage 262 227 title={error.includes("permssions") 263 - ? "Something went wrong on this page.." 264 - : "You cannot access this page.." 228 + ? "You cannot access this page.." 229 + : "Something went wrong on this page.." 265 230 } 266 231 description={error} 267 232 buttons={<> ··· 281 246 <Image src={SadWumpusPic} alt="" height={141} width={124} /> 282 247 </ScreenMessage> 283 248 : 284 - guild?.id ? children : <></> 249 + (guild && loaded.length === 3) ? children : <></> 285 250 } 286 251 287 252 </div >