From 162f8b50df0baa5c0f24ebc1801bae7009a41b57 Mon Sep 17 00:00:00 2001 From: Olly Hearn Date: Tue, 9 Apr 2024 19:44:45 +0300 Subject: [PATCH] working header! --- frontend/app/package-lock.json | 41 +++++++++++++++- frontend/app/package.json | 3 +- frontend/app/src/App.css | 1 - frontend/app/src/App.tsx | 2 + frontend/app/src/components/AuthModal.tsx | 16 +++---- .../app/src/components/HeaderComponent.tsx | 44 +++++++++++------- frontend/app/src/components/authProvider.ts | 1 - frontend/app/src/config/store.ts | 40 ++++++++-------- frontend/app/src/config/style.ts | 8 +++- frontend/app/src/pages/AppRoutes.tsx | 19 ++++++++ frontend/app/src/pages/MainPage.tsx | 19 ++++++++ frontend/app/src/pages/styles.css | 27 +++++++++++ frontend/app/static/logo-square.png | Bin 0 -> 23564 bytes 13 files changed, 172 insertions(+), 49 deletions(-) create mode 100644 frontend/app/src/pages/AppRoutes.tsx create mode 100644 frontend/app/src/pages/MainPage.tsx create mode 100644 frontend/app/src/pages/styles.css create mode 100644 frontend/app/static/logo-square.png diff --git a/frontend/app/package-lock.json b/frontend/app/package-lock.json index b92bd66..34da32a 100644 --- a/frontend/app/package-lock.json +++ b/frontend/app/package-lock.json @@ -13,7 +13,8 @@ "antd": "^5.15.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^9.1.0" + "react-redux": "^9.1.0", + "react-router-dom": "^6.22.3" }, "devDependencies": { "@rsbuild/core": "^0.5.4", @@ -424,6 +425,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rsbuild/core": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-0.5.4.tgz", @@ -4012,6 +4021,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", + "dependencies": { + "@remix-run/router": "1.15.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", + "dependencies": { + "@remix-run/router": "1.15.3", + "react-router": "6.22.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", diff --git a/frontend/app/package.json b/frontend/app/package.json index 1a0092f..a9e8f08 100644 --- a/frontend/app/package.json +++ b/frontend/app/package.json @@ -13,7 +13,8 @@ "antd": "^5.15.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-redux": "^9.1.0" + "react-redux": "^9.1.0", + "react-router-dom": "^6.22.3" }, "devDependencies": { "@rsbuild/core": "^0.5.4", diff --git a/frontend/app/src/App.css b/frontend/app/src/App.css index 164c0a6..525cd30 100644 --- a/frontend/app/src/App.css +++ b/frontend/app/src/App.css @@ -11,7 +11,6 @@ body { line-height: 1.1; text-align: center; flex-direction: column; - justify-content: center; } .content h1 { diff --git a/frontend/app/src/App.tsx b/frontend/app/src/App.tsx index 12a9cd2..51eb2c0 100644 --- a/frontend/app/src/App.tsx +++ b/frontend/app/src/App.tsx @@ -6,6 +6,7 @@ import { theme } from "./config/style"; import { Provider } from "react-redux"; import { store } from "./config/store"; import { MessageInstance } from "antd/es/message/interface"; +import AppRoutes from "./pages/AppRoutes"; export const MessageContext = createContext({} as MessageInstance); @@ -21,6 +22,7 @@ const App = () => {
{contextHolder} +
diff --git a/frontend/app/src/components/AuthModal.tsx b/frontend/app/src/components/AuthModal.tsx index ca64c86..6ae2abd 100644 --- a/frontend/app/src/components/AuthModal.tsx +++ b/frontend/app/src/components/AuthModal.tsx @@ -17,17 +17,16 @@ const AuthModal = (props: { const [loginForm] = Form.useForm(); const [registerForm] = Form.useForm(); + const { data, refetch, isFetching, isError } = useGetUserQuery({}); + useEffect(() => { + if (!isFetching && !isError) { + store.dispatch(updateUser(data)); + } + }, [data, isFetching, useGetUserQuery]); + const [current, setCurrent] = useState("login"); const messageApi = useContext(MessageContext); - // const { data, refetch, isFetching, isError } = useGetUserQuery({}); - // useEffect(() => { - // console.log(data); - // if (!isFetching && !isError) { - // store.dispatch(updateUser(data)); - // } - // }, [data, isFetching, useGetUserQuery]); - const [loginUser, { isLoading: isLoggingIn }] = useLoginMutation(); const [registerUser, { isLoading: isRegistering }] = useRegisterMutation(); @@ -41,6 +40,7 @@ const AuthModal = (props: { .then((data) => { store.dispatch(updateToken(data.access_token)); }) + .then(() => refetch()) .then(() => props.setOpen(false)) .catch(() => messageApi.error("Login failed!")); }; diff --git a/frontend/app/src/components/HeaderComponent.tsx b/frontend/app/src/components/HeaderComponent.tsx index 8e9e229..b91ed21 100644 --- a/frontend/app/src/components/HeaderComponent.tsx +++ b/frontend/app/src/components/HeaderComponent.tsx @@ -1,10 +1,10 @@ -import { UserOutlined } from "@ant-design/icons"; -import { Layout, Menu, MenuProps } from "antd"; +import { LogoutOutlined, UserOutlined } from "@ant-design/icons"; +import { Button, Layout, Menu, MenuProps, Tooltip } from "antd"; import React, { useEffect, useState } from "react"; import AuthModal from "./AuthModal"; import "./styles.css"; -import { getLocalToken, store, updateUser } from "../config/store"; -import { User, useGetUserQuery } from "../slice/AuthApi"; +import { StorePrototype, logOut, store } from "../config/store"; +import { useSelector } from "react-redux"; const { Header } = Layout; @@ -12,31 +12,43 @@ type NullableUser = { name: string | null; username: string } | null; const HeaderComponent = () => { const [authModalOpen, setAuthModalOpen] = useState(false); - store.dispatch(getLocalToken()); - const user: NullableUser = store.getState().auth.user; - // useEffect(() => { - // console.log(data); - // if (!isFetching && !isError) { - // store.dispatch(updateUser(data)); - // } - // }, [data, isFetching, useGetUserQuery]); + const user: NullableUser = useSelector( + (state: StorePrototype) => state.auth.user + ); - console.log(store.getState()); + // const userMenuItems: MenuProps["userMenuItems"] = [ + // { + // label: , + // key: "logout", + // icon: , + // onClick: () => store.dispatch(logOut()), + // }, + // ] const items: MenuProps["items"] = [ { - label: user ? user.username : "Log In", + label: user ? ( + store.dispatch(logOut())}>Log out + } + > + {user.username} + + ) : ( + "Log In" + ), key: "login", icon: , - onClick: () => setAuthModalOpen(true), + onClick: () => !user && setAuthModalOpen(true), }, ]; return ( <> -
+
{ const { data, isFetching, isError } = useGetUserQuery({}); useEffect(() => { - console.log(data); if (!isFetching && !isError) { store.dispatch(updateUser(data)); } diff --git a/frontend/app/src/config/store.ts b/frontend/app/src/config/store.ts index b579579..f8487d3 100644 --- a/frontend/app/src/config/store.ts +++ b/frontend/app/src/config/store.ts @@ -1,42 +1,37 @@ -import { configureStore, createAction, createReducer } from "@reduxjs/toolkit"; +import { + ReducerType, + configureStore, + createAction, + createReducer, +} from "@reduxjs/toolkit"; import { setupListeners } from "@reduxjs/toolkit/query"; import { AuthApi, User } from "../slice/AuthApi"; -export type authState = { +export type AuthDataType = { token: string | null; user: { name: string | null; username: string } | null; }; -const initialAuthState: authState = { +const initialAuthDataState: AuthDataType = { token: null, user: null, }; +export type StorePrototype = { + AuthApi: ReducerType; + auth: AuthDataType; +}; + export const updateToken = createAction("auth/updateToken"); export const getLocalToken = createAction("auth/getLocalToken"); export const updateUser = createAction("auth/updateUser"); - -const parseJwt = (token: string): { sub: string; exp: number } => { - const base64Url = token.split(".")[1]; - const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/"); - const jsonPayload = decodeURIComponent( - window - .atob(base64) - .split("") - .map(function (c) { - return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2); - }) - .join("") - ); - - return JSON.parse(jsonPayload); -}; +export const logOut = createAction("auth/logOut"); export const store = configureStore({ reducer: { // Add the generated reducer as a specific top-level slice [AuthApi.reducerPath]: AuthApi.reducer, - auth: createReducer(initialAuthState, (builder) => { + auth: createReducer(initialAuthDataState, (builder) => { builder.addCase(updateToken, (state, action) => { state.token = action.payload; localStorage.setItem("token", action.payload); @@ -50,6 +45,11 @@ export const store = configureStore({ builder.addCase(updateUser, (state, action) => { state.user = action.payload; }); + builder.addCase(logOut, (state) => { + localStorage.removeItem("token"); + state.token = null; + state.user = null; + }); }), }, // Adding the api middleware enables caching, invalidation, polling, diff --git a/frontend/app/src/config/style.ts b/frontend/app/src/config/style.ts index cb47658..90951ee 100644 --- a/frontend/app/src/config/style.ts +++ b/frontend/app/src/config/style.ts @@ -1,4 +1,6 @@ -export const theme = { +import { ThemeConfig } from "antd"; + +export const theme: ThemeConfig = { components: { Modal: { contentBg: "#001529", @@ -11,6 +13,10 @@ export const theme = { }, Button: { primaryColor: "#001529", + defaultHoverBg: "#001529", + defaultHoverColor: "white", + colorPrimaryBgHover: "#001529", + // colorPrimaryHover: "#001529", }, Message: { contentBg: "#001c36", diff --git a/frontend/app/src/pages/AppRoutes.tsx b/frontend/app/src/pages/AppRoutes.tsx new file mode 100644 index 0000000..6daa0c2 --- /dev/null +++ b/frontend/app/src/pages/AppRoutes.tsx @@ -0,0 +1,19 @@ +import React, { useEffect } from "react"; +import { BrowserRouter, Route, Routes } from "react-router-dom"; +import MainPage from "./MainPage"; +import { useGetUserQuery } from "../slice/AuthApi"; +import { getLocalToken, store, updateUser } from "../config/store"; + +const AppRoutes = () => { + store.dispatch(getLocalToken()); + + return ( + + + + + + ); +}; + +export default AppRoutes; diff --git a/frontend/app/src/pages/MainPage.tsx b/frontend/app/src/pages/MainPage.tsx new file mode 100644 index 0000000..c695094 --- /dev/null +++ b/frontend/app/src/pages/MainPage.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import "./styles.css"; +import logoSquare from "../../static/logo-square.png"; +import { Button } from "antd"; + +const MainPage = () => { + return ( +
+ logo +

Organizing queues were never so simple

+
+ + +
+
+ ); +}; + +export default MainPage; diff --git a/frontend/app/src/pages/styles.css b/frontend/app/src/pages/styles.css new file mode 100644 index 0000000..ec491b7 --- /dev/null +++ b/frontend/app/src/pages/styles.css @@ -0,0 +1,27 @@ +.card { + background: #001529; + margin: 10px; + border-radius: 10px; + } + +.main { + display: flex; + flex-flow: column; + justify-items: center; + align-items: center; + align-content: space-between; +} + +.image { + height: 10vw; + width: auto; +} + +.button-box { + width: 100%; + display: flex; + align-self: center; + flex-flow: row; + justify-items: center; + align-content: space-around; +} \ No newline at end of file diff --git a/frontend/app/static/logo-square.png b/frontend/app/static/logo-square.png new file mode 100644 index 0000000000000000000000000000000000000000..353be97b5eb3e361c1fbc02c2a561a5a481a3f97 GIT binary patch literal 23564 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