Skip to content

Commit bc6aeb1

Browse files
committed
feat(dashboard): ssr
1 parent bb42393 commit bc6aeb1

File tree

2 files changed

+98
-76
lines changed

2 files changed

+98
-76
lines changed

web/lib/queries.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useQuery } from "@tanstack/react-query";
2+
import { createContext, useContext } from "react";
23

34
export interface User {
45
id: string;
@@ -15,7 +16,20 @@ export const API_URL =
1516
? "http://localhost:18103"
1617
: "https://api.chatr.fun";
1718

19+
const UserContext = createContext<User | null>(null);
20+
21+
export const UserProvider = ({
22+
children,
23+
user,
24+
}: {
25+
children: React.ReactNode;
26+
user: User;
27+
}) => {
28+
return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
29+
};
30+
1831
export const useUser = () => {
32+
const user = useContext(UserContext);
1933
const query = useQuery<User | null>({
2034
queryKey: ["user"],
2135
queryFn: async () => {
@@ -27,6 +41,7 @@ export const useUser = () => {
2741

2842
return await res.json();
2943
},
44+
initialData: user,
3045
});
3146

3247
return { user: query.data, isLoading: query.isLoading };

web/pages/dashboard/index.tsx

Lines changed: 83 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import { useRouter } from "next/router";
2-
import { useQuery } from "@tanstack/react-query";
31
import { Button } from "@nextui-org/react";
42
import Link from "next/link";
3+
import { GetServerSidePropsContext } from "next";
54

65
import DefaultLayout from "@/layouts/default";
7-
import { API_URL, useUser } from "@/lib/queries";
6+
import { API_URL, User, UserProvider } from "@/lib/queries";
87
import { subtitle, title } from "@/components/primitives";
9-
import { LoaderIcon } from "@/components/icons";
108
import { ServerIcon } from "@/components/server-icon";
119

1210
interface Guild {
@@ -16,81 +14,90 @@ interface Guild {
1614
botIsInGuild: boolean;
1715
}
1816

19-
export default function Dashboard() {
20-
const router = useRouter();
21-
const { user, isLoading: userLoading } = useUser();
22-
const { data: guilds, isLoading: guildsLoading } = useQuery<Guild[]>({
23-
queryKey: ["guilds"],
24-
queryFn: async () => {
25-
const res = await fetch(`${API_URL}/auth/user/guilds`, {
26-
credentials: "include",
27-
});
17+
export default function Dashboard({
18+
user,
19+
guilds,
20+
}: {
21+
user: User;
22+
guilds: Guild[];
23+
}) {
24+
return (
25+
<UserProvider user={user}>
26+
<DefaultLayout>
27+
<section className="flex flex-col items-center justify-center gap-4 py-8">
28+
<div className="inline-block max-w-lg text-center justify-center">
29+
<h1 className={title()}>Dashboard</h1>
30+
<h4 className={subtitle({ class: "mt-4" })}>
31+
Manage and update your server&apos;s settings.
32+
</h4>
33+
</div>
34+
{guilds.length === 0 ? (
35+
<p>You are not admin in any servers.</p>
36+
) : (
37+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
38+
{guilds.map((guild) => (
39+
<div
40+
key={guild.id}
41+
className="bg-gray-800 p-6 rounded-lg flex flex-col justify-center space-y-4 shadow-lg"
42+
>
43+
<div className="flex flex-col space-y-3 items-center justify-center">
44+
<ServerIcon guild={guild} />
45+
<span className="text-white text-2xl font-bold text-center">
46+
{guild.name}
47+
</span>
48+
</div>
49+
<Button
50+
as={Link}
51+
color={
52+
guild.botIsInGuild
53+
? "secondary"
54+
: "default"
55+
}
56+
href={
57+
guild.botIsInGuild
58+
? `/dashboard/${guild.id}`
59+
: `${API_URL}/invite?guild_id=${guild.id}`
60+
}
61+
variant="shadow"
62+
>
63+
{guild.botIsInGuild
64+
? "Manage"
65+
: "Invite"}
66+
</Button>
67+
</div>
68+
))}
69+
</div>
70+
)}
71+
</section>
72+
</DefaultLayout>
73+
</UserProvider>
74+
);
75+
}
2876

29-
if (res.status === 401) return null;
77+
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
78+
const userResponse = await fetch(`${API_URL}/auth/user`, {
79+
headers: {
80+
cookie: ctx.req.headers.cookie ?? "",
81+
},
82+
});
3083

31-
return await res.json();
84+
if (userResponse.status === 401)
85+
return {
86+
props: { guilds: null },
87+
redirect: {
88+
destination: `${API_URL}/auth/login`,
89+
permanent: false,
90+
},
91+
};
92+
93+
const guildsResponse = await fetch(`${API_URL}/auth/user/guilds`, {
94+
headers: {
95+
cookie: ctx.req.headers.cookie ?? "",
3296
},
3397
});
3498

35-
if (!user && !userLoading) return router.push("/");
99+
const user = await userResponse.json();
100+
const guilds = await guildsResponse.json();
36101

37-
return (
38-
<DefaultLayout>
39-
<section className="flex flex-col items-center justify-center gap-4 py-8">
40-
<div className="inline-block max-w-lg text-center justify-center">
41-
<h1 className={title()}>Dashboard</h1>
42-
<h4 className={subtitle({ class: "mt-4" })}>
43-
Manage and update your server&apos;s settings.
44-
</h4>
45-
</div>
46-
{userLoading || guildsLoading || !guilds ? (
47-
<LoaderIcon
48-
className="animate-spin"
49-
height={56}
50-
width={56}
51-
/>
52-
) : (
53-
<>
54-
{guilds.length === 0 ? (
55-
<p>You are not admin in any servers.</p>
56-
) : (
57-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
58-
{guilds.map((guild) => (
59-
<div
60-
key={guild.id}
61-
className="bg-gray-800 p-6 rounded-lg flex flex-col justify-center space-y-4 shadow-lg"
62-
>
63-
<div className="flex flex-col space-y-3 items-center justify-center">
64-
<ServerIcon guild={guild} />
65-
<span className="text-white text-2xl font-bold text-center">
66-
{guild.name}
67-
</span>
68-
</div>
69-
<Button
70-
as={Link}
71-
color={
72-
guild.botIsInGuild
73-
? "secondary"
74-
: "default"
75-
}
76-
href={
77-
guild.botIsInGuild
78-
? `/dashboard/${guild.id}`
79-
: `${API_URL}/invite?guild_id=${guild.id}`
80-
}
81-
variant="shadow"
82-
>
83-
{guild.botIsInGuild
84-
? "Manage"
85-
: "Invite"}
86-
</Button>
87-
</div>
88-
))}
89-
</div>
90-
)}
91-
</>
92-
)}
93-
</section>
94-
</DefaultLayout>
95-
);
96-
}
102+
return { props: { user, guilds } };
103+
};

0 commit comments

Comments
 (0)