Skip to content

Commit 755ba48

Browse files
committed
display user in header, properly logout, properly parse sessions
1 parent 7dfbf5e commit 755ba48

File tree

3 files changed

+68
-9
lines changed

3 files changed

+68
-9
lines changed

frontend/app/root.tsx

+51-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import React from "react";
2-
import type { LinksFunction, MetaFunction } from "@remix-run/node";
2+
import type {
3+
LinksFunction,
4+
LoaderFunction,
5+
MetaFunction,
6+
} from "@remix-run/node";
7+
import { json } from "@remix-run/node";
38
import {
49
Link,
510
Links,
@@ -9,9 +14,11 @@ import {
914
Scripts,
1015
ScrollRestoration,
1116
useCatch,
17+
useLoaderData,
1218
} from "@remix-run/react";
1319

1420
import tailwindStyles from "~/tailwind.css";
21+
import { getSessionDataFromRequest } from "./utils/session.server";
1522

1623
export const links: LinksFunction = () => [
1724
{ rel: "stylesheet", href: tailwindStyles },
@@ -22,7 +29,13 @@ export const meta: MetaFunction = () => {
2229
return { title: "bogos" };
2330
};
2431

25-
function Document({ children }: { children: React.ReactNode }) {
32+
function Document({
33+
children,
34+
currentUser: { username, avatarUrl } = {},
35+
}: {
36+
children: React.ReactNode;
37+
currentUser: { username?: string; avatarUrl?: string };
38+
}) {
2639
return (
2740
<html lang="en">
2841
<head>
@@ -36,9 +49,20 @@ function Document({ children }: { children: React.ReactNode }) {
3649
<Link to="/" className="text-stone-100 text-xl">
3750
👽 bogos
3851
</Link>
39-
<Link to="/login" className="text-stone-100 text-xl">
40-
login
41-
</Link>
52+
{username ? (
53+
<div className="flex gap-x-6 items-center">
54+
<p className="text-stone-100 text-xl my-0">
55+
<span className="opacity-50">logged in as</span> {username} -{" "}
56+
<Link to="/logout" className="text-stone-100 text-xl">
57+
logout
58+
</Link>
59+
</p>
60+
</div>
61+
) : (
62+
<Link to="/login" className="text-stone-100 text-xl">
63+
login
64+
</Link>
65+
)}
4266
</header>
4367
{children}
4468
<ScrollRestoration />
@@ -49,9 +73,30 @@ function Document({ children }: { children: React.ReactNode }) {
4973
);
5074
}
5175

76+
type LoaderData = {
77+
username?: string;
78+
avatarUrl?: string;
79+
};
80+
81+
export const loader: LoaderFunction = async ({ request }) => {
82+
const sessionData = await getSessionDataFromRequest(request);
83+
84+
if (sessionData !== null) {
85+
const data: LoaderData = {
86+
username: sessionData.username,
87+
avatarUrl: sessionData.avatarUrl,
88+
};
89+
return json(data);
90+
}
91+
92+
return json({});
93+
};
94+
5295
export default function App() {
96+
const data = useLoaderData<LoaderData>();
97+
5398
return (
54-
<Document>
99+
<Document currentUser={data}>
55100
<Outlet />
56101
</Document>
57102
);

frontend/app/routes/logout.tsx

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { ActionFunction, LoaderFunction } from "@remix-run/node";
2+
3+
import { logout } from "~/utils/session.server";
4+
5+
export const action: ActionFunction = async ({ request }) => {
6+
return logout(request);
7+
};
8+
9+
export const loader: LoaderFunction = async ({ request }) => {
10+
return logout(request);
11+
};

frontend/app/utils/session.server.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const SessionDataSchema = z.object({
66
jwt: z.string(),
77
userId: z.number(),
88
username: z.string(),
9-
avatarUrl: z.string(),
9+
avatarUrl: z.string().optional(),
1010
});
1111

1212
type SessionData = z.infer<typeof SessionDataSchema>;
@@ -26,8 +26,11 @@ export function getUserSession(request: Request) {
2626

2727
export async function getSessionDataFromRequest(request: Request) {
2828
const session = await getUserSession(request);
29-
const sessionData = SessionDataSchema.parse(session);
30-
return sessionData;
29+
try {
30+
return SessionDataSchema.parse(session.data);
31+
} catch {
32+
return null;
33+
}
3134
}
3235

3336
if (!config.site.sessionSecret) {

0 commit comments

Comments
 (0)