From c4ad4938315c8c222a97f61f151e7cee156215ed Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 16:16:26 -0800 Subject: [PATCH 01/22] Install wouter --- package-lock.json | 17 ++++++++++++++++- package.json | 3 ++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index feca2021..4780f284 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,8 @@ "react-dom": "^17.0.2", "react-i18next": "^11.15.3", "react-router-dom": "^6.2.1", - "sass": "^1.49.0" + "sass": "^1.49.0", + "wouter": "^2.8.0-alpha.2" }, "devDependencies": { "@types/node": "17.0.11", @@ -6721,6 +6722,14 @@ "node": ">=0.10.0" } }, + "node_modules/wouter": { + "version": "2.8.0-alpha.2", + "resolved": "https://registry.npmjs.org/wouter/-/wouter-2.8.0-alpha.2.tgz", + "integrity": "sha512-aPsL5m5rW9RiceClOmGj6t5gn9Ut2TJVr98UDi1u9MIRNYiYVflg6vFIjdDYJ4IAyH0JdnkSgGwfo0LQS3k2zg==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -11470,6 +11479,12 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wouter": { + "version": "2.8.0-alpha.2", + "resolved": "https://registry.npmjs.org/wouter/-/wouter-2.8.0-alpha.2.tgz", + "integrity": "sha512-aPsL5m5rW9RiceClOmGj6t5gn9Ut2TJVr98UDi1u9MIRNYiYVflg6vFIjdDYJ4IAyH0JdnkSgGwfo0LQS3k2zg==", + "requires": {} + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index d5a6e71c..bb39087f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "react-dom": "^17.0.2", "react-i18next": "^11.15.3", "react-router-dom": "^6.2.1", - "sass": "^1.49.0" + "sass": "^1.49.0", + "wouter": "^2.8.0-alpha.2" }, "devDependencies": { "@types/node": "17.0.11", From ade50a04e5c3df270c8b54973f2213ef9e39a9d7 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 20:46:57 -0800 Subject: [PATCH 02/22] Rewrite / to /new --- next.config.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/next.config.js b/next.config.js index 4e417b7f..fc60c38f 100644 --- a/next.config.js +++ b/next.config.js @@ -1,11 +1,20 @@ /** @type {import('next').NextConfig} */ const path = require('path') -module.exports = {reactStrictMode: true, +module.exports = { + reactStrictMode: true, sassOptions: { prependData: '@import "variables";', includePaths: [path.join(__dirname, 'styles')], }, + async rewrites() { + return [ + { + source: '/', + destination: '/new' + } + ] + }, webpack(config) { config.module.rules.push({ test: /\.svg$/, @@ -18,4 +27,3 @@ module.exports = {reactStrictMode: true, return config; }, }; - From fcd544536d8b033daa2bf69ec42256e4992e4dd1 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 20:47:21 -0800 Subject: [PATCH 03/22] Create app-wide layout with Header --- components/Layout/index.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 components/Layout/index.tsx diff --git a/components/Layout/index.tsx b/components/Layout/index.tsx new file mode 100644 index 00000000..3b78f2c8 --- /dev/null +++ b/components/Layout/index.tsx @@ -0,0 +1,17 @@ +import type { ReactElement } from 'react' +import Header from '~components/Header' + +interface Props { + children: ReactElement +} + +const Layout = ({children}: Props) => { + return ( + <> +
+
{children}
+ + ) +} + +export default Layout \ No newline at end of file From 374e19b0071368c375c78b865bbe45a7bc84fe50 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 20:47:34 -0800 Subject: [PATCH 04/22] Add cookies and Layout to index page --- pages/_app.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pages/_app.tsx b/pages/_app.tsx index b0a9ef71..3471ecc3 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,9 +1,17 @@ import '../styles/globals.scss' import type { AppProps } from 'next/app' +import { CookiesProvider } from 'react-cookie' +import Layout from '~components/Layout' function MyApp({ Component, pageProps }: AppProps) { - return + return ( + + + + + + ) } export default MyApp From 86432df4f5d121218d9fb672bf30e451dd8ade6a Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 20:49:09 -0800 Subject: [PATCH 05/22] Remove old index page --- pages/index.tsx | 23 ------ routes/NewRoute/index.tsx | 22 ------ routes/PartyRoute/index.tsx | 135 ------------------------------------ 3 files changed, 180 deletions(-) delete mode 100644 pages/index.tsx delete mode 100644 routes/NewRoute/index.tsx delete mode 100644 routes/PartyRoute/index.tsx diff --git a/pages/index.tsx b/pages/index.tsx deleted file mode 100644 index 7b1540f2..00000000 --- a/pages/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import type { NextPage } from 'next' -import Head from 'next/head' -import styles from '../styles/Home.module.css' - -import { CookiesProvider } from 'react-cookie' -import { BrowserRouter } from 'react-router-dom' - -import App from '~/components/App' - -const Home: NextPage = () => { - if (typeof window === "undefined") - return null - - return ( - - - - - - ) -} - -export default Home diff --git a/routes/NewRoute/index.tsx b/routes/NewRoute/index.tsx deleted file mode 100644 index 9ac20b2c..00000000 --- a/routes/NewRoute/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react' -import Party from '~components/Party' - -const NewRoute: React.FC = () => { - function callback(path: string) { - // This is scuffed, how do we do this natively? - window.history.replaceState(null, `Grid Tool`, `${path}`) - } - - return ( -
- -
- ) -} - -export default NewRoute \ No newline at end of file diff --git a/routes/PartyRoute/index.tsx b/routes/PartyRoute/index.tsx deleted file mode 100644 index b1db1fdf..00000000 --- a/routes/PartyRoute/index.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { withCookies, useCookies } from 'react-cookie' -import { useParams } from 'react-router-dom' -import api from '~utils/api' - -import Party from '~components/Party' -import Button from '~components/Button' - -interface Props { - hash: string -} - - -const PartyRoute: React.FC = () => { - const params = useParams() - - const [found, setFound] = useState(false) - const [loading, setLoading] = useState(true) - const [editable, setEditable] = useState(false) - - const [characters, setCharacters] = useState>({}) - const [weapons, setWeapons] = useState>({}) - const [summons, setSummons] = useState>({}) - - const [mainWeapon, setMainWeapon] = useState() - const [mainSummon, setMainSummon] = useState() - const [friendSummon, setFriendSummon] = useState() - - const [partyId, setPartyId] = useState('') - const [extra, setExtra] = useState(false) - const [cookies, setCookie] = useCookies(['user']) - const shortcode = params.hash || '' - - - useEffect(() => { - fetchGrid(shortcode) - }, []) - - async function fetchGrid(shortcode: string) { - return api.endpoints.parties.getOne({ id: shortcode }) - .then(response => { - const party = response.data.party - - const partyUser = party.user_id - const loggedInUser = (cookies.user) ? cookies.user.user_id : '' - - if (partyUser != undefined && loggedInUser != undefined && partyUser === loggedInUser) - setEditable(true) - - let characters: GridArray = {} - let weapons: GridArray = {} - let summons: GridArray = {} - - party.characters.forEach((gridCharacter: GridCharacter) => { - if (gridCharacter.position != null) - characters[gridCharacter.position] = gridCharacter.character - }) - - party.weapons.forEach((gridWeapon: GridWeapon) => { - if (gridWeapon.mainhand) - setMainWeapon(gridWeapon.weapon) - else if (!gridWeapon.mainhand && gridWeapon.position != null) - weapons[gridWeapon.position] = gridWeapon.weapon - }) - - party.summons.forEach((gridSummon: GridSummon) => { - if (gridSummon.main) - setMainSummon(gridSummon.summon) - else if (gridSummon.friend) - setFriendSummon(gridSummon.summon) - else if (!gridSummon.main && !gridSummon.friend && gridSummon.position != null) - summons[gridSummon.position] = gridSummon.summon - }) - - setExtra(response.data.party.is_extra) - setFound(true) - setLoading(false) - setCharacters(characters) - setWeapons(weapons) - setSummons(summons) - setPartyId(party.id) - }) - .catch(error => { - if (error.response != null) { - if (error.response.status == 404) { - setFound(false) - setLoading(false) - } - } else { - console.error(error) - } - }) - } - - function render() { - return ( -
- -
- ) - } - - function renderNotFound() { - return ( -
-

There's no grid here.

- -
- ) - } - - if (!found && !loading) { - return renderNotFound() - } else if (found && !loading) { - return render() - } else { - return (
) - } -} - -export default - withCookies( - PartyRoute - ) \ No newline at end of file From f9874c270e106caa77610b52378c2c5fb740607f Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 20:51:28 -0800 Subject: [PATCH 06/22] Move NewRoute to a Next.js page --- pages/new/index.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 pages/new/index.tsx diff --git a/pages/new/index.tsx b/pages/new/index.tsx new file mode 100644 index 00000000..9ac20b2c --- /dev/null +++ b/pages/new/index.tsx @@ -0,0 +1,22 @@ +import React from 'react' +import Party from '~components/Party' + +const NewRoute: React.FC = () => { + function callback(path: string) { + // This is scuffed, how do we do this natively? + window.history.replaceState(null, `Grid Tool`, `${path}`) + } + + return ( +
+ +
+ ) +} + +export default NewRoute \ No newline at end of file From d5343293cbe43d09974690725ad2e82bed8460e2 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 20:51:38 -0800 Subject: [PATCH 07/22] Move PartyRoute to a Next.js page --- pages/p/[slug].tsx | 152 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 pages/p/[slug].tsx diff --git a/pages/p/[slug].tsx b/pages/p/[slug].tsx new file mode 100644 index 00000000..7cbe900f --- /dev/null +++ b/pages/p/[slug].tsx @@ -0,0 +1,152 @@ +import React, { useEffect, useState } from 'react' +import { withCookies, useCookies } from 'react-cookie' +import { useRouter } from 'next/router' +import api from '~utils/api' + +import Party from '~components/Party' +import Button from '~components/Button' + +interface Props { + hash: string +} + +const PartyRoute: React.FC = () => { + const router = useRouter() + const { slug } = router.query + + const [found, setFound] = useState(false) + const [loading, setLoading] = useState(true) + const [editable, setEditable] = useState(false) + + const [characters, setCharacters] = useState>({}) + const [weapons, setWeapons] = useState>({}) + const [summons, setSummons] = useState>({}) + + const [mainWeapon, setMainWeapon] = useState() + const [mainSummon, setMainSummon] = useState() + const [friendSummon, setFriendSummon] = useState() + + const [partyId, setPartyId] = useState('') + const [extra, setExtra] = useState(false) + const [cookies, _] = useCookies(['user']) + + useEffect(() => { + async function fetchGrid(shortcode: string) { + return api.endpoints.parties.getOne({ id: shortcode }) + .then(response => { + const party = response.data.party + + const partyUser = (party.user_id) ? party.user_id : undefined + const loggedInUser = (cookies.user) ? cookies.user.user_id : '' + + if (partyUser != undefined && loggedInUser != undefined && partyUser === loggedInUser) + setEditable(true) + + const characters = populateCharacters(party.characters) + const weapons = populateWeapons(party.weapons) + const summons = populateSummons(party.summons) + + setExtra(response.data.party.is_extra) + setFound(true) + setLoading(false) + setCharacters(characters) + setWeapons(weapons) + setSummons(summons) + setPartyId(party.id) + }) + .catch(error => { + if (error.response != null) { + if (error.response.status == 404) { + setFound(false) + setLoading(false) + } + } else { + console.error(error) + } + }) + } + + function populateCharacters(list: [GridCharacter]) { + let characters: GridArray = {} + + list.forEach((object: GridCharacter) => { + if (object.position != null) + characters[object.position] = object.character + }) + + return characters + } + + function populateWeapons(list: [GridWeapon]) { + let weapons: GridArray = {} + + list.forEach((object: GridWeapon) => { + if (object.mainhand) + setMainWeapon(object.weapon) + else if (!object.mainhand && object.position != null) + weapons[object.position] = object.weapon + }) + + return weapons + } + + function populateSummons(list: [GridSummon]) { + let summons: GridArray = {} + + list.forEach((object: GridSummon) => { + if (object.main) + setMainSummon(object.summon) + else if (object.friend) + setFriendSummon(object.summon) + else if (!object.main && !object.friend && object.position != null) + summons[object.position] = object.summon + }) + + return summons + } + + const shortcode: string = slug as string + fetchGrid(shortcode) + }, [slug, cookies.user]) + + function render() { + return ( +
+ +
+ ) + } + + function renderNotFound() { + return ( +
+

There's no grid here.

+ +
+ ) + } + + if (!found && !loading) { + return renderNotFound() + } else if (found && !loading) { + return render() + } else { + return (
) + } +} + +export default + withCookies( + PartyRoute + ) \ No newline at end of file From 55d037f6f4f1d103eb46da198955e6d8ce4894b9 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 23:03:23 -0800 Subject: [PATCH 08/22] Added a context to track logged-in and editable state --- context/AppContext.tsx | 10 ++++++++++ pages/_app.tsx | 16 ++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 context/AppContext.tsx diff --git a/context/AppContext.tsx b/context/AppContext.tsx new file mode 100644 index 00000000..ab66c95c --- /dev/null +++ b/context/AppContext.tsx @@ -0,0 +1,10 @@ +import { createContext } from 'react' + +const AppContext = createContext({ + authenticated: false, + editable: false, + setAuthenticated: (auth: boolean) => {}, + setEditable: (editable: boolean) => {} +}) + +export default AppContext \ No newline at end of file diff --git a/pages/_app.tsx b/pages/_app.tsx index 3471ecc3..f01ddfaa 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,15 +1,23 @@ import '../styles/globals.scss' -import type { AppProps } from 'next/app' +import { useState } from 'react' import { CookiesProvider } from 'react-cookie' + import Layout from '~components/Layout' +import AppContext from '~context/AppContext' + +import type { AppProps } from 'next/app' function MyApp({ Component, pageProps }: AppProps) { + const [authenticated, setAuthenticated] = useState(false) + const [editable, setEditable] = useState(false) return ( - - - + + + + + ) } From e02c55665e7e60eac0f7bce30b50d684a2759e25 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 31 Jan 2022 23:05:15 -0800 Subject: [PATCH 09/22] Convert to Next Router --- components/Header/index.tsx | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/components/Header/index.tsx b/components/Header/index.tsx index 39220a86..62ca0da6 100644 --- a/components/Header/index.tsx +++ b/components/Header/index.tsx @@ -1,29 +1,26 @@ import React, { useEffect, useState } from 'react' -import { useNavigate, useLocation } from 'react-router-dom' import { useCookies } from 'react-cookie' +import { useRouter } from 'next/router' import Button from '~components/Button' import HeaderMenu from '~components/HeaderMenu' import './index.scss' -interface Props { - navigate: (pathname: string) => void -} +interface Props {} const Header = (props: Props) => { const [username, setUsername] = useState(undefined) - const [cookies, setCookie, removeCookie] = useCookies(['user']) + const [cookies, _, removeCookie] = useCookies(['user']) - let navigate = useNavigate() - let location = useLocation() - - const route = (pathname: string) => props.navigate(pathname) + const router = useRouter() useEffect(() => { if (cookies.user) { setUsername(cookies.user.username) console.log(`Logged in as user "${cookies.user.username}"`) + } else { + console.log('You are currently not logged in.') } }, [cookies]) @@ -39,18 +36,18 @@ const Header = (props: Props) => { } function newParty() { - navigate('/') + router.push('/') } function logout() { removeCookie('user') window.history.replaceState(null, `Grid Tool`, `/`) - navigate(0) + // navigate(0) } return ( -