diff --git a/package-lock.json b/package-lock.json index 7974517f..6c6fa62a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "firebase": "^10.9.0", "graphemer": "^1.4.0", "jotai": "^2.7.1", + "jotai-location": "^0.5.4", "next": "14.1.4", "openapi-fetch": "^0.9.3", "openapi-typescript-helpers": "^0.0.7", @@ -2089,7 +2090,6 @@ }, "node_modules/@clack/prompts/node_modules/is-unicode-supported": { "version": "1.3.0", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -9284,6 +9284,14 @@ } } }, + "node_modules/jotai-location": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/jotai-location/-/jotai-location-0.5.4.tgz", + "integrity": "sha512-IqpyYLAF6HgoDoJVlX66IGvgrugCA1LJybT01NqenpdwypPtUB6u0cnJZMbN6axU+Yl2FTI6l+4x9IWh4WGFRA==", + "peerDependencies": { + "jotai": ">=1.11.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index e547a332..1c18bc2d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "firebase": "^10.9.0", "graphemer": "^1.4.0", "jotai": "^2.7.1", + "jotai-location": "^0.5.4", "next": "14.1.4", "openapi-fetch": "^0.9.3", "openapi-typescript-helpers": "^0.0.7", diff --git a/src/common_components/Button.tsx b/src/common_components/Button.tsx index 1cfcbf12..eca1988b 100644 --- a/src/common_components/Button.tsx +++ b/src/common_components/Button.tsx @@ -12,7 +12,6 @@ export const Button: FC = ({ color, size = "medium", className, children, const button = cva({ base: { borderRadius: "sm", - display: "block", cursor: "pointer", borderWidth: 2, borderStyle: "solid", diff --git a/src/common_components/auth/AuthUI.tsx b/src/common_components/auth/AuthUI.tsx index 693072a8..f9a5e2cb 100644 --- a/src/common_components/auth/AuthUI.tsx +++ b/src/common_components/auth/AuthUI.tsx @@ -1,15 +1,18 @@ +"use client"; import React, { FC, PropsWithChildren } from "react"; import { Header } from "@/common_components/header/Header"; import SigninPage from "@/common_components/auth/signin/page"; import SignupPage from "@/common_components/auth/signup/page"; -import { atom, useAtomValue } from "jotai"; +import { useAtomValue } from "jotai"; import { useAuthState } from "@/lib/firebase"; import { Loading } from "@/common_components/Loading"; import { css } from "@styled-system/css"; import { EmailVerification } from "@/common_components/auth/EmailVerification"; import { usePathname } from "next/navigation"; +import { atomWithHash } from "jotai-location"; +import { ResetPassword } from "./resetPassword/ResetPassword"; -export const authModeAtom = atom<"signIn" | "signUp">("signIn"); +export const authModeAtom = atomWithHash<"signIn" | "signUp" | "resetPassword">("authMode", "signIn"); export const AuthUI: FC = ({ children }) => { const authMode = useAtomValue(authModeAtom); @@ -27,6 +30,22 @@ export const AuthUI: FC = ({ children }) => { return children; } + const Component: React.FC = () => { + switch (authMode) { + case "signIn": + return ; + + case "signUp": + return ; + + case "resetPassword": + return ; + + default: + return <>; + } + }; + return ( <>
@@ -40,7 +59,7 @@ export const AuthUI: FC = ({ children }) => { ) : authState.user ? ( <>{authState.user.emailVerified ? <>{children} : } ) : ( - <>{authMode === "signIn" ? : } + )} ); diff --git a/src/common_components/auth/EmailVerification.tsx b/src/common_components/auth/EmailVerification.tsx index b595dfbb..b6df2058 100644 --- a/src/common_components/auth/EmailVerification.tsx +++ b/src/common_components/auth/EmailVerification.tsx @@ -1,12 +1,12 @@ import { center } from "@styled-system/patterns"; -import { css } from "@styled-system/css"; -import { Button } from "@/common_components/Button"; +import { css, cx } from "@styled-system/css"; import SendButton from "@/assets/SendButton.svg?url"; import Image from "next/image"; import { sendEmailVerification } from "firebase/auth"; import { useAuthState } from "@/lib/firebase"; import { useState } from "react"; import toast from "react-hot-toast"; +import { buttonStyle } from "@/recipes/button"; export const EmailVerification = () => { const authState = useAuthState(); @@ -58,24 +58,26 @@ export const EmailVerification = () => {

再送しても届かない場合は時間を空けてからお試しください

- + {isSent && (

確認メールを再送しました diff --git a/src/common_components/auth/resetPassword/ResetPassword.tsx b/src/common_components/auth/resetPassword/ResetPassword.tsx new file mode 100644 index 00000000..f8a7343a --- /dev/null +++ b/src/common_components/auth/resetPassword/ResetPassword.tsx @@ -0,0 +1,104 @@ +import { basicErrorMessageStyle, basicFormStyle } from "@/common_components/formFields/styles"; +import { buttonStyle } from "@/recipes/button"; +import { css, cx } from "@styled-system/css"; +import { center, vstack } from "@styled-system/patterns"; +import { getAuth, sendPasswordResetEmail } from "firebase/auth"; +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import toast from "react-hot-toast"; +import Image from "next/image"; +import Triangle from "@/assets/Triangle.svg?url"; +import { useSetAtom } from "jotai"; +import { authModeAtom } from "@/common_components/auth/AuthUI"; +const ResetPasswordForm: React.FC = () => { + const { + register, + handleSubmit, + formState: { errors }, + } = useForm<{ email: string }>(); + const [isSent, setIsSent] = useState(false); + const onSubmit = (data: { email: string }) => { + toast.promise(sendPasswordResetEmail(getAuth(), data.email), { + loading: "メールを送信しています", + success: () => { + setIsSent(true); + return "メールを送信しました"; + }, + error: "メールの送信に失敗しました", + }); + }; + return ( +

+ + + {isSent &&

メールを送信しました。受信トレイをご確認ください

} +
+ ); +}; + +export const ResetPassword: React.FC = () => { + const setAuthMode = useSetAtom(authModeAtom); + return ( +
+
+

パスワードのリセット

+ +
+ + +
+
+
+ ); +}; diff --git a/src/common_components/auth/signin/SignInPage.tsx b/src/common_components/auth/signin/SignInPage.tsx index 32644662..f6751800 100644 --- a/src/common_components/auth/signin/SignInPage.tsx +++ b/src/common_components/auth/signin/SignInPage.tsx @@ -5,7 +5,7 @@ import { useForm } from "react-hook-form"; import toast from "react-hot-toast"; import { css, cx } from "@styled-system/css"; import { basicErrorMessageStyle, basicFormStyle } from "@/common_components/formFields/styles"; -import { Button } from "@/common_components/Button"; +import { buttonStyle } from "@/recipes/button"; type SignInInput = { email: string; password: string }; @@ -88,9 +88,17 @@ export const SigninForm: React.FC = () => { {errors.password && {errors.password.message}} {errors.root && {errors.root.message}}
- + ); diff --git a/src/common_components/auth/signin/page.tsx b/src/common_components/auth/signin/page.tsx index f09f77af..99424a57 100644 --- a/src/common_components/auth/signin/page.tsx +++ b/src/common_components/auth/signin/page.tsx @@ -7,7 +7,7 @@ import Image from "next/image"; import Triangle from "@/assets/Triangle.svg?url"; import { authModeAtom } from "@/common_components/auth/AuthUI"; import { useSetAtom } from "jotai"; -import { center } from "@styled-system/patterns"; +import { center, vstack } from "@styled-system/patterns"; const SigninPage: NextPage = () => { const setAuthMode = useSetAtom(authModeAtom); @@ -18,10 +18,7 @@ const SigninPage: NextPage = () => { minHeight: "calc(100vh - token(spacing.20))", })}>
{ width: "fit-content", maxWidth: "90%", })}> -

ログイン

+

サインイン

-
+
+ + +
+
)}