diff --git a/src/app/apollo-provider.tsx b/src/app/apollo-provider.tsx index 2fe7605..1d17ace 100644 --- a/src/app/apollo-provider.tsx +++ b/src/app/apollo-provider.tsx @@ -9,7 +9,7 @@ import { import { setContext } from "@apollo/client/link/context" import { type ReactNode, useMemo } from "react" -import { getToken } from "../lib/auth" +import { getToken } from "@/lib/auth" function createApolloClient() { const httpLink = createHttpLink({ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 3821c21..b6ef9cb 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,7 +6,7 @@ import { Noto_Sans_JP } from "next/font/google" import "./globals.css" import { InitColorSchemeScript } from "@mui/material" -import theme from "../theme" +import theme from "@/theme" import ApolloProviderClient from "./apollo-provider" const notoSansJp = Noto_Sans_JP({ diff --git a/src/app/login.tsx b/src/app/login/page.tsx similarity index 56% rename from src/app/login.tsx rename to src/app/login/page.tsx index 5fcd0ee..e4643be 100644 --- a/src/app/login.tsx +++ b/src/app/login/page.tsx @@ -1,4 +1,4 @@ -import LoginForm from "../components/login-form" +import LoginForm from "@/components/login-form" export default function LoginPage() { return diff --git a/src/app/page.tsx b/src/app/page.tsx index b370386..d384055 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,4 @@ -import Monitor from "../components/monitor" +import Monitor from "@/components/monitor" export default function Home() { return diff --git a/src/components/app_bar/account_menu_icon.tsx b/src/components/app_bar/account_menu_icon.tsx index 521b75a..8fdee49 100644 --- a/src/components/app_bar/account_menu_icon.tsx +++ b/src/components/app_bar/account_menu_icon.tsx @@ -3,7 +3,7 @@ import AccountCircleIcon from "@mui/icons-material/AccountCircle" import { Box, IconButton, Menu, MenuItem } from "@mui/material" import { useRouter } from "next/navigation" import { useState } from "react" -import { setToken } from "../../lib/auth" +import { setToken } from "@/lib/auth" export default function AccountMenuIcon() { const apolloClient = useApolloClient() diff --git a/src/components/auth-redirect.ts b/src/components/auth-redirect.ts new file mode 100644 index 0000000..ae82223 --- /dev/null +++ b/src/components/auth-redirect.ts @@ -0,0 +1,23 @@ +"use client" + +import { usePathname, useRouter } from "next/navigation" +import { useEffect } from "react" +import { hasToken } from "@/lib/auth" + +export function useAuthRedirect() { + const router = useRouter() + const pathname = usePathname() + + useEffect(() => { + const loggedIn = hasToken() + + if (!loggedIn && pathname !== "/login") { + router.replace("/login") + return + } + + if (loggedIn && pathname === "/login") { + router.replace("/") + } + }, [router, pathname]) +} diff --git a/src/components/login-form.tsx b/src/components/login-form.tsx index 359835b..61d07b0 100644 --- a/src/components/login-form.tsx +++ b/src/components/login-form.tsx @@ -3,16 +3,18 @@ import { Box, Button, Container, TextField } from "@mui/material" import Head from "next/head" import { useRouter } from "next/navigation" -import { useEffect } from "react" import { Controller, useForm } from "react-hook-form" -import { hasToken, setToken } from "../lib/auth" +import { setToken } from "@/lib/auth" import AnonymousAppBar from "./app_bar/anonymous_app_bar" +import { useAuthRedirect } from "./auth-redirect" export interface LoginValues { token: string } export default function LoginForm() { + useAuthRedirect() + const router = useRouter() const { control, handleSubmit } = useForm({ defaultValues: { @@ -25,12 +27,6 @@ export default function LoginForm() { router.push("/") } - useEffect(() => { - if (hasToken()) { - router.push("/") - } - }) - return (
diff --git a/src/components/monitor.tsx b/src/components/monitor.tsx index 2f001f0..47a84c2 100644 --- a/src/components/monitor.tsx +++ b/src/components/monitor.tsx @@ -9,20 +9,19 @@ import { Toolbar, Typography, } from "@mui/material" -import { useRouter } from "next/navigation" import { useEffect, useState } from "react" +import MainAppBar from "@/components/app_bar/main_app_bar" +import Co2Chart from "@/components/chart/co2_chart" +import HumidityChart from "@/components/chart/humidity_chart" +import LightChart from "@/components/chart/light_chart" +import TemperatureChart from "@/components/chart/temperature_chart" +import SmokePingChartImage from "@/components/smoke_ping_chart_image" import dayjs from "@/lib/dayjs" -import MainAppBar from "../components/app_bar/main_app_bar" -import Co2Chart from "../components/chart/co2_chart" -import HumidityChart from "../components/chart/humidity_chart" -import LightChart from "../components/chart/light_chart" -import TemperatureChart from "../components/chart/temperature_chart" -import SmokePingChartImage from "../components/smoke_ping_chart_image" -import { hasToken } from "../lib/auth" -import { useGetMonitorQuery } from "../lib/graphql-types" +import { useGetMonitorQuery } from "@/lib/graphql-types" +import { useAuthRedirect } from "./auth-redirect" export default function Monitor() { - const router = useRouter() + useAuthRedirect() const smokePingNames = process.env.NEXT_PUBLIC_SMOKEPING_NAMES?.split(",") ?? [] @@ -114,12 +113,6 @@ export default function Monitor() { ? calibratedData?.mhz19Co2?.[co2DataCount - 1]?.value : undefined - useEffect(() => { - if (!hasToken()) { - router.push("/login/") - } - }) - // Refresh data every 1 minute // Reload page every 60 minutes useEffect(() => {