diff --git a/.gitignore b/.gitignore
index 88b6f0d..ae3981f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
+
+# editors
+.vscode
diff --git a/components/dialog.tsx b/components/dialog.tsx
new file mode 100644
index 0000000..79aed16
--- /dev/null
+++ b/components/dialog.tsx
@@ -0,0 +1,22 @@
+import { Center, VStack, Text } from "@chakra-ui/react"
+
+export type FullScreenDialogProps = {
+ title: String;
+ children?: JSX.Element | JSX.Element[];
+}
+
+export const FullScreenDialog = ({ title, children }: FullScreenDialogProps) => (
+
+
+ {title}
+
+ {children}
+
+
+)
+
diff --git a/components/error_boundary.tsx b/components/error_boundary.tsx
new file mode 100644
index 0000000..4030e47
--- /dev/null
+++ b/components/error_boundary.tsx
@@ -0,0 +1,58 @@
+import React, { ErrorInfo } from "react";
+import { FullScreenDialog } from "./dialog";
+import { Center, Flex, Link, Text, VStack } from "@chakra-ui/react";
+
+type ErrorBoundaryProps = {
+ children?: JSX.Element | JSX.Element[];
+}
+
+type ErrorState = {
+ errorMessage?: string | JSX.Element;
+}
+
+export default class ErrorBoundary extends React.Component {
+ constructor(props: ErrorBoundaryProps) {
+ super(props)
+ this.state = {}
+ }
+
+ static getDerivedStateFromError(error: Error) {
+ return { errorMessage: ErrorBoundary.translateErrorMessage(error) };
+ }
+
+ static translateErrorMessage(error: Error): string | JSX.Element {
+ switch (error.message) {
+ case "Network Error": return "Błąd połączenia z serwerem."
+ case "Request failed with status code 401": return (
+ Nie masz dostępu do tej strony będąc niezalogowanym!
+ Kliknij tutaj aby przejść do logowania.
+ )
+ default: return error.message
+ }
+ }
+
+ componentDidCatch(error: Error, errorInfo: ErrorInfo) {
+ console.log("Uncaught error thrown: " + error + ". Error info: " + errorInfo)
+ }
+
+ render() {
+ if (this.state.errorMessage) {
+ return (
+
+ Coś poszło nie tak. Wiadomość błędu:
+ {this.state.errorMessage}
+
+ );
+ } else {
+ return this.props.children;
+ }
+ }
+}
+
+// idea by David Barral:
+// https://medium.com/trabe/catching-asynchronous-errors-in-react-using-error-boundaries-5e8a5fd7b971
+// thanks
+export const usePromiseError = () => {
+ const [_, setError] = React.useState(null);
+ return React.useCallback(err => setError(() => { throw err }), [setError]);
+};
diff --git a/components/navbar.tsx b/components/navbar.tsx
index 71d7118..59af9ff 100644
--- a/components/navbar.tsx
+++ b/components/navbar.tsx
@@ -3,9 +3,15 @@ import {
Box, Button, ButtonProps, Center, Flex, IconButton, LayoutProps, Link,
LinkProps,
Menu, MenuButton, MenuItem, MenuList, Spacer,
+ Image,
+ Text,
} from "@chakra-ui/react";
+import { useEffect, useState } from "react";
+import { getProfileByUserId, Profile } from "../lib/profile";
+import { getSession } from "../lib/auth";
+import { usePromiseError } from "./error_boundary";
-const LOGIN_DISCORD_URL = "/api/auth/discord"
+const LOGIN_DISCORD_URL = "/auth/discord"
type NavItem = {
title: string;
@@ -32,18 +38,35 @@ const NAV_ITEMS: Array = [
},
]
+const NavBar = () => {
+ // if profile -> loaded profile for current session successfully
+ // if null -> not logged in
+ // if undefined -> page is loading / fetching profile data from api
+ const [profile, setProfile] = useState(undefined)
+ const throwError = usePromiseError()
+ useEffect(() => {
+ let session = getSession()
+ if (session) {
+ getProfileByUserId(session.userId)
+ .then(setProfile)
+ .catch(throwError)
+ } else {
+ setProfile(null)
+ }
+ }, [])
+
+ return (
+
+
+
+
+
+
+
+ );
+}
-const NavBar = () => (
-
-
-
-
-
-
-
-)
-
-const DesktopNavBar = () => (
+const DesktopNavBar = ({ profile }: { profile: Profile | null | undefined }) => (
@@ -62,14 +85,15 @@ const DesktopNavBar = () => (
-
+
)
-const MobileNavBar = () => (
+const MobileNavBar = ({ profile }: { profile: Profile | null | undefined }) => (
@@ -92,7 +118,9 @@ const MobileNavBar = () => (
-
+
)
@@ -117,12 +145,73 @@ const Logo = (props: LinkProps) => (
)
+type MenuProps = {
+ profile: Profile | null | undefined
+ buttonProps?: ButtonProps
+}
+
+const UserMenu = ({ profile, buttonProps }: MenuProps) => {
+ if (profile === undefined) {
+ return <>>
+ } else if (profile === null) {
+ return
+ } else {
+ return
+ }
+}
+
const LoginWithDiscord = (props: ButtonProps) => (
-