From 3d141cf05bda7afee026d98115d0154600513c90 Mon Sep 17 00:00:00 2001 From: Takeshi Kimata <117462761+kimatata@users.noreply.github.com> Date: Sun, 19 May 2024 11:14:04 +0900 Subject: [PATCH] Implement Auth provide user info --- frontend/messages/en.json | 1 + frontend/messages/ja.json | 1 + frontend/src/app/[locale]/DropdownAccount.tsx | 64 +++++++++++++++++++ frontend/src/app/[locale]/Header.tsx | 2 + frontend/src/app/[locale]/TokenProvider.tsx | 25 ++++++++ .../[locale]/{auth => account}/authControl.ts | 2 + .../[locale]/{auth => account}/authPage.tsx | 10 ++- .../app/[locale]/{auth => account}/layout.tsx | 0 frontend/src/app/[locale]/account/page.tsx | 27 ++++++++ .../{auth => account}/signin/page.tsx | 0 .../{auth => account}/signup/page.tsx | 0 .../{auth => account}/validate.test.ts | 0 .../[locale]/{auth => account}/validate.ts | 0 frontend/src/app/[locale]/layout.tsx | 2 +- frontend/src/app/[locale]/providers.tsx | 10 ++- frontend/types/user.ts | 14 +++- 16 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 frontend/src/app/[locale]/DropdownAccount.tsx create mode 100644 frontend/src/app/[locale]/TokenProvider.tsx rename frontend/src/app/[locale]/{auth => account}/authControl.ts (96%) rename frontend/src/app/[locale]/{auth => account}/authPage.tsx (94%) rename frontend/src/app/[locale]/{auth => account}/layout.tsx (100%) create mode 100644 frontend/src/app/[locale]/account/page.tsx rename frontend/src/app/[locale]/{auth => account}/signin/page.tsx (100%) rename frontend/src/app/[locale]/{auth => account}/signup/page.tsx (100%) rename frontend/src/app/[locale]/{auth => account}/validate.test.ts (100%) rename frontend/src/app/[locale]/{auth => account}/validate.ts (100%) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index dd11ebe..35bb441 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -25,6 +25,7 @@ "projects": "Projects" }, "Auth": { + "account": "Account", "signup": "Sign up", "signin": "Sign in", "or_signup": "You need sign up?", diff --git a/frontend/messages/ja.json b/frontend/messages/ja.json index 4b41664..fde1998 100644 --- a/frontend/messages/ja.json +++ b/frontend/messages/ja.json @@ -25,6 +25,7 @@ "projects": "プロジェクト" }, "Auth": { + "account": "アカウント", "signup": "新規登録", "signin": "サインイン", "or_signup": "新規登録ページ", diff --git a/frontend/src/app/[locale]/DropdownAccount.tsx b/frontend/src/app/[locale]/DropdownAccount.tsx new file mode 100644 index 0000000..4939ab6 --- /dev/null +++ b/frontend/src/app/[locale]/DropdownAccount.tsx @@ -0,0 +1,64 @@ +"use client"; +import { + Button, + DropdownTrigger, + Dropdown, + DropdownMenu, + DropdownItem, +} from "@nextui-org/react"; +import { User, ChevronDown } from "lucide-react"; +import { useContext } from "react"; +import { TokenContext } from "./TokenProvider"; +import { Link } from "@/src/navigation"; + +type Props = { + locale: string; +}; + +const signinItems = [ + { uid: "account", title: "Account", href: "/account" }, + { uid: "signout", title: "Sign out", href: "/account/signout" }, +]; + +const signoutItems = [ + { uid: "signin", title: "Sign in", href: "/account/signin" }, +]; + +export default function LangSwitch({ locale }: Props) { + const context = useContext(TokenContext); + return ( + + + + + {context.token ? ( + + {signinItems.map((entry) => ( + + + {entry.title} + + + ))} + + ) : ( + + {signoutItems.map((entry) => ( + + + {entry.title} + + + ))} + + )} + + ); +} diff --git a/frontend/src/app/[locale]/Header.tsx b/frontend/src/app/[locale]/Header.tsx index 33056e1..118b340 100644 --- a/frontend/src/app/[locale]/Header.tsx +++ b/frontend/src/app/[locale]/Header.tsx @@ -16,6 +16,7 @@ import LangSwitch from "./LangSwitch"; import { ThemeSwitch } from "@/components/theme-switch"; import { GithubIcon } from "@/components/icons"; import Image from "next/image"; +import DropdownAccount from "./DropdownAccount"; export default function Header(params: { locale: string }) { const t = useTranslations("Header"); @@ -102,6 +103,7 @@ export default function Header(params: { locale: string }) { + diff --git a/frontend/src/app/[locale]/TokenProvider.tsx b/frontend/src/app/[locale]/TokenProvider.tsx new file mode 100644 index 0000000..4851df8 --- /dev/null +++ b/frontend/src/app/[locale]/TokenProvider.tsx @@ -0,0 +1,25 @@ +"use client"; +import { createContext, useState } from "react"; +import { TokenType, UserType } from "@/types/user"; +import { TokenProps } from "@/types/user"; + +const defaultTokenContext = { + token: null, + setUser: (token: TokenType) => {}, +}; +const TokenContext = createContext(defaultTokenContext); + +const TokenProvider = ({ children }: TokenProps) => { + const [token, setToken] = useState(null); + const tokenContext = { + token, + setToken, + }; + + return ( + {children} + ); +}; + +export { TokenContext }; +export default TokenProvider; diff --git a/frontend/src/app/[locale]/auth/authControl.ts b/frontend/src/app/[locale]/account/authControl.ts similarity index 96% rename from frontend/src/app/[locale]/auth/authControl.ts rename to frontend/src/app/[locale]/account/authControl.ts index f7470c0..83ad23b 100644 --- a/frontend/src/app/[locale]/auth/authControl.ts +++ b/frontend/src/app/[locale]/account/authControl.ts @@ -20,6 +20,7 @@ async function signUp(newUser: UserType) { } const accessToken = await response.json(); storeToken(accessToken); + return accessToken; } catch (error: any) { console.error("Error sign up:", error); throw error; @@ -44,6 +45,7 @@ async function signIn(signInUser: UserType) { } const accessToken = await response.json(); storeToken(accessToken); + return accessToken; } catch (error: any) { console.error("Error sign in:", error); throw error; diff --git a/frontend/src/app/[locale]/auth/authPage.tsx b/frontend/src/app/[locale]/account/authPage.tsx similarity index 94% rename from frontend/src/app/[locale]/auth/authPage.tsx rename to frontend/src/app/[locale]/account/authPage.tsx index 3f7a682..69d4fc9 100644 --- a/frontend/src/app/[locale]/auth/authPage.tsx +++ b/frontend/src/app/[locale]/account/authPage.tsx @@ -1,6 +1,6 @@ "use client"; import React from "react"; -import { useState } from "react"; +import { useState, useContext } from "react"; import { Input, Button, Card, CardHeader, CardBody } from "@nextui-org/react"; import { Link } from "@/src/navigation"; import { ChevronRight, Eye, EyeOff } from "lucide-react"; @@ -8,6 +8,7 @@ import { UserType, AuthMessages } from "@/types/user"; import { roles } from "@/config/selection"; import { signUp, signIn } from "./authControl"; import { isValidEmail, isValidPassword } from "./validate"; +import { TokenContext } from "../TokenProvider"; type Props = { isSignup: Boolean; messages: AuthMessages; @@ -15,6 +16,7 @@ type Props = { }; export default function AuthPage({ isSignup, messages, locale }: Props) { + const context = useContext(TokenContext); const [user, setUser] = useState({ id: null, email: "", @@ -59,14 +61,16 @@ export default function AuthPage({ isSignup, messages, locale }: Props) { const submit = async () => { if (isSignup) { try { - await signUp(user); + const token = await signUp(user); + context.setToken(token); // Move to signin page } catch { setErrorMessage(messages.signupError); } } else { try { - signIn(user); + const token = await signIn(user); + context.setToken(token); // Move to signin page } catch { setErrorMessage(messages.signinError); diff --git a/frontend/src/app/[locale]/auth/layout.tsx b/frontend/src/app/[locale]/account/layout.tsx similarity index 100% rename from frontend/src/app/[locale]/auth/layout.tsx rename to frontend/src/app/[locale]/account/layout.tsx diff --git a/frontend/src/app/[locale]/account/page.tsx b/frontend/src/app/[locale]/account/page.tsx new file mode 100644 index 0000000..6cd153a --- /dev/null +++ b/frontend/src/app/[locale]/account/page.tsx @@ -0,0 +1,27 @@ +import { useTranslations } from "next-intl"; +import { Input, Button, Card, CardHeader, CardBody } from "@nextui-org/react"; +import { Link } from "@/src/navigation"; + +export default function Page(params: { locale: string }) { + const t = useTranslations("Auth"); + + return ( + + +

{t('account')}

+ {/* + + */} +
+ + afgdsfg + +
+ ); +} diff --git a/frontend/src/app/[locale]/auth/signin/page.tsx b/frontend/src/app/[locale]/account/signin/page.tsx similarity index 100% rename from frontend/src/app/[locale]/auth/signin/page.tsx rename to frontend/src/app/[locale]/account/signin/page.tsx diff --git a/frontend/src/app/[locale]/auth/signup/page.tsx b/frontend/src/app/[locale]/account/signup/page.tsx similarity index 100% rename from frontend/src/app/[locale]/auth/signup/page.tsx rename to frontend/src/app/[locale]/account/signup/page.tsx diff --git a/frontend/src/app/[locale]/auth/validate.test.ts b/frontend/src/app/[locale]/account/validate.test.ts similarity index 100% rename from frontend/src/app/[locale]/auth/validate.test.ts rename to frontend/src/app/[locale]/account/validate.test.ts diff --git a/frontend/src/app/[locale]/auth/validate.ts b/frontend/src/app/[locale]/account/validate.ts similarity index 100% rename from frontend/src/app/[locale]/auth/validate.ts rename to frontend/src/app/[locale]/account/validate.ts diff --git a/frontend/src/app/[locale]/layout.tsx b/frontend/src/app/[locale]/layout.tsx index 1cccba8..722c970 100644 --- a/frontend/src/app/[locale]/layout.tsx +++ b/frontend/src/app/[locale]/layout.tsx @@ -34,7 +34,7 @@ export default function RootLayout({ fontSans.variable )} > - +
{children}
diff --git a/frontend/src/app/[locale]/providers.tsx b/frontend/src/app/[locale]/providers.tsx index 412b800..3870280 100644 --- a/frontend/src/app/[locale]/providers.tsx +++ b/frontend/src/app/[locale]/providers.tsx @@ -6,17 +6,23 @@ import { useRouter } from "next/navigation"; import { ThemeProvider as NextThemesProvider } from "next-themes"; import { ThemeProviderProps } from "next-themes/dist/types"; +import TokenProvider from "./TokenProvider"; +import { TokenProps } from "@/types/user"; + export interface ProvidersProps { children: React.ReactNode; themeProps?: ThemeProviderProps; + userProps?: TokenProps; } -export function Providers({ children, themeProps }: ProvidersProps) { +export function Providers({ children, themeProps, userProps }: ProvidersProps) { const router = useRouter(); return ( - {children} + + {children} + ); } diff --git a/frontend/types/user.ts b/frontend/types/user.ts index 4455a39..821f03e 100644 --- a/frontend/types/user.ts +++ b/frontend/types/user.ts @@ -5,6 +5,18 @@ export type UserType = { username: string; role: number; avatarPath: string; +} | null; + +export type TokenProps = { + children?: React.ReactNode; +}; + +export type TokenType = { + token: { + access_token: string; + user: UserType; + }; + setToken: () => {}; }; export type AuthMessages = { @@ -23,4 +35,4 @@ export type AuthMessages = { emailNotExist: string; signupError: string; signinError: string; -}; \ No newline at end of file +};