diff --git a/app/components/header.tsx b/app/components/header.tsx
index 53964da..f8659a5 100644
--- a/app/components/header.tsx
+++ b/app/components/header.tsx
@@ -3,6 +3,7 @@ import { Tabs } from "@heroui/react";
import { Button } from "@heroui/react";
import { useNavigate, useLocation } from "react-router";
import porning from "../images/porning.svg";
+import User from "./user";
export function Header() {
const location = useLocation();
@@ -42,7 +43,7 @@ export function Header() {
-
+
);
diff --git a/app/components/user.tsx b/app/components/user.tsx
new file mode 100644
index 0000000..2a68017
--- /dev/null
+++ b/app/components/user.tsx
@@ -0,0 +1,40 @@
+import { Button, Avatar, Typography, Dropdown, Label, Separator } from "@heroui/react";
+import { useAuth } from "~/hooks/auth";
+
+export default function User() {
+ const {user, login, logout} = useAuth();
+
+ if (user === null) {
+ return ;
+ }
+
+ return (
+
+
+
+ handleAction(String(key), logout)}>
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function handleAction(key: string, logout: () => Promise) {
+ if (key === "settings") {
+ console.log("settings");
+ } else {
+ logout();
+ }
+}
\ No newline at end of file
diff --git a/app/hooks/auth.tsx b/app/hooks/auth.tsx
new file mode 100644
index 0000000..cf629c9
--- /dev/null
+++ b/app/hooks/auth.tsx
@@ -0,0 +1,63 @@
+import { useEffect, useState, createContext, useContext, type PropsWithChildren } from "react";
+import { useSearchParams } from "react-router";
+
+type User = {
+ id: string,
+ steamid: string,
+ name: string,
+ avatar: string
+}
+
+type AuthContextType = {
+ user: User | null,
+ login: () => void,
+ logout: () => Promise
+}
+
+const AuthContext = createContext({
+ user: null,
+ login: () => {},
+ logout: async () => {}
+});
+
+export function AuthProvider({children}: PropsWithChildren) {
+ const [user, setUser] = useState(null);
+ const [searchParams, setSeachParams] = useSearchParams();
+
+ useEffect(() => {
+ const load = async () => {
+
+ if (searchParams.get("openid.ns") !== null) {
+ let response = await fetch("http://localhost:8080/login?" + searchParams.toString()).then(r => r.text());
+ setSeachParams({}, {replace: true});
+ if (response === "nok") {
+ // TODO: signal error to user
+ }
+ }
+
+ let data = await fetch("http://localhost:8080/me", {credentials: "include"})
+ .then(r => r.json())
+
+ console.log(data);
+ setUser(data);
+ }
+
+ load();
+ }, []);
+
+ const login = () => {
+ location.replace("https://steamcommunity.com/openid/login?openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.mode=checkid_setup&openid.ns=http://specs.openid.net/auth/2.0&openid.realm=http://localhost:5173&openid.return_to=http://localhost:5173");
+ };
+
+ const logout = async () => {
+ setUser(null);
+ };
+
+ return
+ {children}
+
+}
+
+export function useAuth() {
+ return useContext(AuthContext);
+}
\ No newline at end of file
diff --git a/app/root.tsx b/app/root.tsx
index 63f4b0d..9c96f36 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -9,6 +9,7 @@ import {
import type { Route } from "./+types/root";
import "./app.css";
+import { AuthProvider } from "./hooks/auth";
export const links: Route.LinksFunction = () => [
{ rel: "preconnect", href: "https://fonts.googleapis.com" },
@@ -33,7 +34,9 @@ export function Layout({ children }: { children: React.ReactNode }) {
- {children}
+
+ {children}
+