From 3b07d27e15e9a8a57bb0bc208c8c4b8227c3e58d Mon Sep 17 00:00:00 2001 From: huanfeng Date: Wed, 23 Jul 2025 07:16:53 +0800 Subject: [PATCH 1/9] Adding auth provider --- components/Newsfeed/Newsfeed.tsx | 5 +++-- components/auth/AuthRedirect.tsx | 20 ++++++++++++++++++++ components/auth/Provider.tsx | 19 +++++++++++++++++++ components/auth/index.ts | 1 + components/auth/redux.ts | 5 ++++- 5 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 components/auth/AuthRedirect.tsx create mode 100644 components/auth/Provider.tsx diff --git a/components/Newsfeed/Newsfeed.tsx b/components/Newsfeed/Newsfeed.tsx index cc124c307..fe9ea4707 100644 --- a/components/Newsfeed/Newsfeed.tsx +++ b/components/Newsfeed/Newsfeed.tsx @@ -16,11 +16,12 @@ import { import ProfileSettingsModal from "components/EditProfilePage/ProfileSettingsModal" import { NewsfeedCard } from "components/NewsfeedCard/NewsfeedCard" import { ProfileButtons } from "components/ProfilePage/ProfileButtons" +import { useAuthRedirect } from "components/auth/AuthRedirect" export default function Newsfeed() { const { t } = useTranslation("common") - const { user } = useAuth() + const { user, loading: authLoading } = useAuthRedirect() const uid = user?.uid const { result: profile, loading } = usePublicProfile(uid) const isUser = user?.uid !== undefined @@ -191,7 +192,7 @@ export default function Newsfeed() { return ( <> - {loading ? ( + {authLoading || loading ? ( diff --git a/components/auth/AuthRedirect.tsx b/components/auth/AuthRedirect.tsx new file mode 100644 index 000000000..e985dbb9e --- /dev/null +++ b/components/auth/AuthRedirect.tsx @@ -0,0 +1,20 @@ +import { useEffect } from 'react'; +import { useRouter } from 'next/router'; +import { useAuth } from '../auth'; // Adjust this path to your actual useAuth hook + +export function useAuthRedirect(isAuthRequired: boolean = true) { + const { user, loading } = useAuth(); + const router = useRouter(); + + useEffect(() => { + if (!loading) { // Wait until authentication state is loaded + if (isAuthRequired && !user) { + const redirectPath = router.asPath; + // console.log("Redirecting to login:", redirectPath); // For debugging + router.push(`/login?redirect=${encodeURIComponent(redirectPath)}`); + } + } + }, [user, loading, router, isAuthRequired]); // Dependencies for useEffect + + return { user, loading }; // Return these for use in the component if needed +} \ No newline at end of file diff --git a/components/auth/Provider.tsx b/components/auth/Provider.tsx new file mode 100644 index 000000000..6e69febf3 --- /dev/null +++ b/components/auth/Provider.tsx @@ -0,0 +1,19 @@ +import { useEffect } from "react" +import { getAuth, onAuthStateChanged, User } from "firebase/auth" +import { useDispatch } from "react-redux" +import { authChanged } from "./redux" + +export const Provider: React.FC> = ({ children }) => { + const dispatch = useDispatch() + + useEffect(() => { + const auth = getAuth() + const unsubscribe = onAuthStateChanged(auth, (user: User | null) => { + dispatch(authChanged({ user })) + }) + + return () => unsubscribe() + }, []) + + return <>{children} +} diff --git a/components/auth/index.ts b/components/auth/index.ts index 97c2bd18f..ffbeb5431 100644 --- a/components/auth/index.ts +++ b/components/auth/index.ts @@ -3,3 +3,4 @@ export * from "./service" export { default as SignInWithButton } from "./SignInWithButton" export { default as SignOut } from "./SignOut" export * from "./types" +export { Provider } from "./Provider" \ No newline at end of file diff --git a/components/auth/redux.ts b/components/auth/redux.ts index fc3c97ce3..cf1b622a4 100644 --- a/components/auth/redux.ts +++ b/components/auth/redux.ts @@ -23,12 +23,14 @@ export interface State { /** True iff user is signed in */ authenticated: boolean authFlowStep: AuthFlowStep + loading: boolean } const initialState: State = { authenticated: false, user: undefined, - authFlowStep: null + authFlowStep: null, + loading: true } export const { @@ -45,6 +47,7 @@ export const { state.user = payload.user state.claims = payload.claims state.authenticated = Boolean(payload.user) + state.loading = false }, authStepChanged(state, action: PayloadAction) { state.authFlowStep = action.payload From c78328e478bd9b012f9fa3812d19c8f18c895526 Mon Sep 17 00:00:00 2001 From: huanfeng Date: Wed, 23 Jul 2025 09:41:30 +0800 Subject: [PATCH 2/9] Create an Login page --- components/Login/Login.tsx | 70 ++++++++++++++++++++++++ components/auth/AuthRedirect.tsx | 2 +- components/auth/ProtectedPageWrapper.tsx | 25 +++++++++ pages/login.tsx | 15 +++++ 4 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 components/Login/Login.tsx create mode 100644 components/auth/ProtectedPageWrapper.tsx create mode 100644 pages/login.tsx diff --git a/components/Login/Login.tsx b/components/Login/Login.tsx new file mode 100644 index 000000000..7e54dd51f --- /dev/null +++ b/components/Login/Login.tsx @@ -0,0 +1,70 @@ +import { useForm } from "react-hook-form" +import { useRouter } from "next/router" +import { useSignInWithEmailAndPassword, SignInWithEmailAndPasswordData } from "../auth/hooks" +import { Form, Stack, Button, Alert } from "../bootstrap" +import Input from "../forms/Input" +import PasswordInput from "../forms/PasswordInput" +import { useTranslation } from "next-i18next" +import { LoadingButton } from "../buttons" +import SocialSignOnButtons from "components/auth/SocialSignOnButtons" +import Divider from "../Divider/Divider" + +export default function Login() { + const router = useRouter() + const redirect = (router.query.redirect as string) || "/" + const { t } = useTranslation("auth") + + const { + register, + handleSubmit, + formState: { errors }, + } = useForm() + + const signIn = useSignInWithEmailAndPassword() + + const success = () => { + const safeRedirect = redirect.startsWith("/") ? redirect : "/" + router.replace(safeRedirect) + } + const onSubmit = handleSubmit( credentials => { + signIn.execute(credentials).then(success) + }) + + + return ( +
+ {signIn.error && {signIn.error.message}} + + + + + + + + {t("signIn")} + + + {t("or")} + + + +
+ ) +} \ No newline at end of file diff --git a/components/auth/AuthRedirect.tsx b/components/auth/AuthRedirect.tsx index e985dbb9e..1de58fcbc 100644 --- a/components/auth/AuthRedirect.tsx +++ b/components/auth/AuthRedirect.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useRouter } from 'next/router'; -import { useAuth } from '../auth'; // Adjust this path to your actual useAuth hook +import { useAuth } from '../auth'; export function useAuthRedirect(isAuthRequired: boolean = true) { const { user, loading } = useAuth(); diff --git a/components/auth/ProtectedPageWrapper.tsx b/components/auth/ProtectedPageWrapper.tsx new file mode 100644 index 000000000..f49065741 --- /dev/null +++ b/components/auth/ProtectedPageWrapper.tsx @@ -0,0 +1,25 @@ +import { useAuth } from '.' +import { useRouter } from "next/router" +import { useEffect } from "react" + +interface ProtectedPageWrapperProps { + children: React.ReactNode +} + +export const ProtectedPageWrapper = ({ children }: ProtectedPageWrapperProps) => { + const { user, loading } = useAuth() + const router = useRouter() + + useEffect(() => { + if (!loading && !user) { + const currentPath = router.asPath + router.replace(`/login?redirect=${encodeURIComponent(currentPath)}`) + } + }, [user, loading, router]) + + if (loading || !user) { + return
Loading...
+ } + + return <>{children} +} \ No newline at end of file diff --git a/pages/login.tsx b/pages/login.tsx new file mode 100644 index 000000000..72482082a --- /dev/null +++ b/pages/login.tsx @@ -0,0 +1,15 @@ +import { createPage } from "../components/page" +import Login from "components/Login/login" + +export default createPage({ + title: "Login", + Page: () => +}) +import { serverSideTranslations } from "next-i18next/serverSideTranslations" +export async function getStaticProps({ locale }: any) { + return { + props: { + ...(await serverSideTranslations(locale, ["auth", "common"])) + } + } +} \ No newline at end of file From 2080d2fae6f21cefcbb4c4b237773a8032bad391 Mon Sep 17 00:00:00 2001 From: huanfeng Date: Wed, 23 Jul 2025 10:42:13 +0800 Subject: [PATCH 3/9] refactor(auth): update requireAuth to handle loading and redirect to login --- components/Login/Login.tsx | 95 +++++++++++++++--------- components/Newsfeed/Newsfeed.tsx | 5 +- components/auth/AuthRedirect.tsx | 20 ----- components/auth/ProtectedPageWrapper.tsx | 25 ------- components/auth/Provider.tsx | 4 +- components/auth/index.ts | 2 +- components/auth/service.tsx | 20 +++-- pages/login.tsx | 4 +- pages/newsfeed.tsx | 5 +- public/locales/en/auth.json | 4 +- 10 files changed, 88 insertions(+), 96 deletions(-) delete mode 100644 components/auth/AuthRedirect.tsx delete mode 100644 components/auth/ProtectedPageWrapper.tsx diff --git a/components/Login/Login.tsx b/components/Login/Login.tsx index 7e54dd51f..3c2c55876 100644 --- a/components/Login/Login.tsx +++ b/components/Login/Login.tsx @@ -1,7 +1,19 @@ import { useForm } from "react-hook-form" import { useRouter } from "next/router" -import { useSignInWithEmailAndPassword, SignInWithEmailAndPasswordData } from "../auth/hooks" -import { Form, Stack, Button, Alert } from "../bootstrap" +import { + useSignInWithEmailAndPassword, + SignInWithEmailAndPasswordData +} from "../auth/hooks" +import { + Form, + Stack, + Button, + Alert, + Container, + Row, + Col, + Card +} from "../bootstrap" import Input from "../forms/Input" import PasswordInput from "../forms/PasswordInput" import { useTranslation } from "next-i18next" @@ -17,7 +29,7 @@ export default function Login() { const { register, handleSubmit, - formState: { errors }, + formState: { errors } } = useForm() const signIn = useSignInWithEmailAndPassword() @@ -26,45 +38,58 @@ export default function Login() { const safeRedirect = redirect.startsWith("/") ? redirect : "/" router.replace(safeRedirect) } - const onSubmit = handleSubmit( credentials => { + const onSubmit = handleSubmit(credentials => { signIn.execute(credentials).then(success) }) - return ( -
- {signIn.error && {signIn.error.message}} + + + + +

{t("signInToAccess")}

+ + + {signIn.error && ( + {signIn.error.message} + )} - - + + - + - - {t("signIn")} - + + {t("signIn")} + - {t("or")} + {t("or")} - - - + router.replace(redirect)} + /> + + +
+ +
+
) -} \ No newline at end of file +} diff --git a/components/Newsfeed/Newsfeed.tsx b/components/Newsfeed/Newsfeed.tsx index fe9ea4707..cc124c307 100644 --- a/components/Newsfeed/Newsfeed.tsx +++ b/components/Newsfeed/Newsfeed.tsx @@ -16,12 +16,11 @@ import { import ProfileSettingsModal from "components/EditProfilePage/ProfileSettingsModal" import { NewsfeedCard } from "components/NewsfeedCard/NewsfeedCard" import { ProfileButtons } from "components/ProfilePage/ProfileButtons" -import { useAuthRedirect } from "components/auth/AuthRedirect" export default function Newsfeed() { const { t } = useTranslation("common") - const { user, loading: authLoading } = useAuthRedirect() + const { user } = useAuth() const uid = user?.uid const { result: profile, loading } = usePublicProfile(uid) const isUser = user?.uid !== undefined @@ -192,7 +191,7 @@ export default function Newsfeed() { return ( <> - {authLoading || loading ? ( + {loading ? ( diff --git a/components/auth/AuthRedirect.tsx b/components/auth/AuthRedirect.tsx deleted file mode 100644 index 1de58fcbc..000000000 --- a/components/auth/AuthRedirect.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { useEffect } from 'react'; -import { useRouter } from 'next/router'; -import { useAuth } from '../auth'; - -export function useAuthRedirect(isAuthRequired: boolean = true) { - const { user, loading } = useAuth(); - const router = useRouter(); - - useEffect(() => { - if (!loading) { // Wait until authentication state is loaded - if (isAuthRequired && !user) { - const redirectPath = router.asPath; - // console.log("Redirecting to login:", redirectPath); // For debugging - router.push(`/login?redirect=${encodeURIComponent(redirectPath)}`); - } - } - }, [user, loading, router, isAuthRequired]); // Dependencies for useEffect - - return { user, loading }; // Return these for use in the component if needed -} \ No newline at end of file diff --git a/components/auth/ProtectedPageWrapper.tsx b/components/auth/ProtectedPageWrapper.tsx deleted file mode 100644 index f49065741..000000000 --- a/components/auth/ProtectedPageWrapper.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useAuth } from '.' -import { useRouter } from "next/router" -import { useEffect } from "react" - -interface ProtectedPageWrapperProps { - children: React.ReactNode -} - -export const ProtectedPageWrapper = ({ children }: ProtectedPageWrapperProps) => { - const { user, loading } = useAuth() - const router = useRouter() - - useEffect(() => { - if (!loading && !user) { - const currentPath = router.asPath - router.replace(`/login?redirect=${encodeURIComponent(currentPath)}`) - } - }, [user, loading, router]) - - if (loading || !user) { - return
Loading...
- } - - return <>{children} -} \ No newline at end of file diff --git a/components/auth/Provider.tsx b/components/auth/Provider.tsx index 6e69febf3..be783908c 100644 --- a/components/auth/Provider.tsx +++ b/components/auth/Provider.tsx @@ -3,7 +3,9 @@ import { getAuth, onAuthStateChanged, User } from "firebase/auth" import { useDispatch } from "react-redux" import { authChanged } from "./redux" -export const Provider: React.FC> = ({ children }) => { +export const Provider: React.FC> = ({ + children +}) => { const dispatch = useDispatch() useEffect(() => { diff --git a/components/auth/index.ts b/components/auth/index.ts index ffbeb5431..51ab7bfc7 100644 --- a/components/auth/index.ts +++ b/components/auth/index.ts @@ -3,4 +3,4 @@ export * from "./service" export { default as SignInWithButton } from "./SignInWithButton" export { default as SignOut } from "./SignOut" export * from "./types" -export { Provider } from "./Provider" \ No newline at end of file +export { Provider } from "./Provider" diff --git a/components/auth/service.tsx b/components/auth/service.tsx index f21730599..8951a235c 100644 --- a/components/auth/service.tsx +++ b/components/auth/service.tsx @@ -8,6 +8,7 @@ import { useAppDispatch } from "../hooks" import { createService } from "../service" import { authChanged, useAuth } from "./redux" import { Claim } from "./types" +import { Row, Spinner } from "../bootstrap" export const { Provider } = createService(() => { const dispatch = useAppDispatch() @@ -76,13 +77,22 @@ export function requireAuth( Component: React.FC> ) { return function ProtectedRoute() { - const { user } = useAuth() + const { user, loading } = useAuth() const router = useRouter() useEffect(() => { - if (user === null) { - router.push({ pathname: "/" }) + if (!loading && !user) { + const currentPath = router.asPath + router.replace(`/login?redirect=${encodeURIComponent(currentPath)}`) } - }, [router, user]) + }, [user, loading, router]) + + if (loading) { + return ( + + + + ) + } return user ? : null } @@ -92,6 +102,6 @@ export function requireAuth( * Redirects user after logging out. */ export async function signOutAndRedirectToHome() { - await auth.signOut() Router.push("/") + await auth.signOut() } diff --git a/pages/login.tsx b/pages/login.tsx index 72482082a..9ad67a3f8 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,5 +1,5 @@ import { createPage } from "../components/page" -import Login from "components/Login/login" +import Login from "components/Login/Login" export default createPage({ title: "Login", @@ -12,4 +12,4 @@ export async function getStaticProps({ locale }: any) { ...(await serverSideTranslations(locale, ["auth", "common"])) } } -} \ No newline at end of file +} diff --git a/pages/newsfeed.tsx b/pages/newsfeed.tsx index f68c104da..55699516f 100644 --- a/pages/newsfeed.tsx +++ b/pages/newsfeed.tsx @@ -1,11 +1,12 @@ import { createPage } from "../components/page" import Newsfeed from "components/Newsfeed/Newsfeed" +import { requireAuth } from "../components/auth" export default createPage({ title: "Newsfeed", - Page: () => { + Page: requireAuth(() => { return - } + }) }) // this must only be on pages in the pages folder diff --git a/public/locales/en/auth.json b/public/locales/en/auth.json index 8a5b6f0a9..f7eb02454 100644 --- a/public/locales/en/auth.json +++ b/public/locales/en/auth.json @@ -54,7 +54,7 @@ "subscribeNewsletter": "Click here to subscribe to our newsletter", "verifyEmail": "Verify your email address", "verifyLinkSent": "Please verify your email for your account by clicking the verification link we sent to your email. You will be required to verify your email before submitting testimony.", - "setUpProfile": "Set Up Your Profile" - + "setUpProfile": "Set Up Your Profile", + "signInToAccess": "Login required to access this the content" } \ No newline at end of file From 65ce0ab92e4bebe1fb9d2a6732e26057b474980d Mon Sep 17 00:00:00 2001 From: huanfeng Date: Wed, 30 Jul 2025 08:35:33 +0800 Subject: [PATCH 4/9] Solved the login component duplicated issues --- components/Login/login.tsx | 132 ++++++++++++++++++++++++++---------- pages/login.tsx | 2 +- public/locales/en/auth.json | 3 +- 3 files changed, 99 insertions(+), 38 deletions(-) diff --git a/components/Login/login.tsx b/components/Login/login.tsx index 2934562e3..31d51312a 100644 --- a/components/Login/login.tsx +++ b/components/Login/login.tsx @@ -1,36 +1,96 @@ -import { useTranslation } from "next-i18next" -import styled from "styled-components" -import { Container } from "../bootstrap" -import { SignInWithButton } from "components/auth" - -export default function LoginPage() { - const { t } = useTranslation("auth") - - const StyledContainer = styled(Container)` - @media (min-width: 768px) { - } - ` - - return ( - -
-
-
-
- {t("probablySignedOut")} -
-
-
- {t("pleaseConsider")} -
-
-
- -
-
-
-
-
-
- ) -} +import { useForm } from "react-hook-form" + import { useRouter } from "next/router" + import { + useSignInWithEmailAndPassword, + SignInWithEmailAndPasswordData + } from "../auth/hooks" + import { + Form, + Stack, + Alert, + Container, + Row, + Col, + Card + } from "../bootstrap" + import Input from "../forms/Input" + import PasswordInput from "../forms/PasswordInput" + import { useTranslation } from "next-i18next" + import { LoadingButton } from "../buttons" + import SocialSignOnButtons from "components/auth/SocialSignOnButtons" + import Divider from "../Divider/Divider" + + export default function Login() { + const router = useRouter() + const redirect = (router.query.redirect as string) || "/" + console.log(redirect); + + const { t } = useTranslation("auth") + + const { + register, + handleSubmit, + formState: { errors } + } = useForm() + + const signIn = useSignInWithEmailAndPassword() + + const success = () => { + const safeRedirect = redirect.startsWith("/") ? redirect : "/" + router.replace(safeRedirect) + } + const onSubmit = handleSubmit(credentials => { + signIn.execute(credentials).then(success) + }) + + return ( + + + + +

{t("signInToAccess")}

+ +
+ {signIn.error && ( + {signIn.error.message} + )} + + + + + + + + {t("signIn")} + + + {t("or")} + + router.replace(redirect)} + /> + +
+
+ +
+
+ ) + } \ No newline at end of file diff --git a/pages/login.tsx b/pages/login.tsx index 9ad67a3f8..71bbe2b91 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,5 +1,5 @@ import { createPage } from "../components/page" -import Login from "components/Login/Login" +import Login from "components/Login/login" export default createPage({ title: "Login", diff --git a/public/locales/en/auth.json b/public/locales/en/auth.json index ef2142ae5..8808cd946 100644 --- a/public/locales/en/auth.json +++ b/public/locales/en/auth.json @@ -56,5 +56,6 @@ "verifyLinkSent": "Please verify your email for your account by clicking the verification link we sent to your email. You will be required to verify your email before submitting testimony.", "setUpProfile": "Set Up Your Profile", "probablySignedOut": "You were possibly signed out while trying to go to a page that needs to be signed in to function", - "pleaseConsider": "Please consider logging in first:" + "pleaseConsider": "Please consider logging in first:", + "signInToAccess": "Login required to access the contents" } \ No newline at end of file From 77163d0dfd9306c12b5cebea35a04152ecc88817 Mon Sep 17 00:00:00 2001 From: huanfeng Date: Wed, 30 Jul 2025 08:54:48 +0800 Subject: [PATCH 5/9] Update import paths to use correct casing for Login.tsx --- .../EditProfilePage/EditProfilePage.tsx | 2 +- components/Login/login.tsx | 158 ++++++++---------- components/Newsfeed/Newsfeed.tsx | 2 +- pages/edit-profile/[[...docName]].tsx | 5 +- pages/login.tsx | 2 +- 5 files changed, 79 insertions(+), 90 deletions(-) diff --git a/components/EditProfilePage/EditProfilePage.tsx b/components/EditProfilePage/EditProfilePage.tsx index f885bd6f6..9b39e79f7 100644 --- a/components/EditProfilePage/EditProfilePage.tsx +++ b/components/EditProfilePage/EditProfilePage.tsx @@ -25,7 +25,7 @@ import { } from "./StyledEditProfileComponents" import { TestimoniesTab } from "./TestimoniesTab" import { useFlags } from "components/featureFlags" -import LoginPage from "components/Login/login" +import LoginPage from "components/Login/Login" import { PendingUpgradeBanner } from "components/PendingUpgradeBanner" const tabTitle = ["about-you", "testimonies", "following"] as const diff --git a/components/Login/login.tsx b/components/Login/login.tsx index 31d51312a..f68a9dfa3 100644 --- a/components/Login/login.tsx +++ b/components/Login/login.tsx @@ -1,96 +1,86 @@ import { useForm } from "react-hook-form" - import { useRouter } from "next/router" - import { - useSignInWithEmailAndPassword, - SignInWithEmailAndPasswordData - } from "../auth/hooks" - import { - Form, - Stack, - Alert, - Container, - Row, - Col, - Card - } from "../bootstrap" - import Input from "../forms/Input" - import PasswordInput from "../forms/PasswordInput" - import { useTranslation } from "next-i18next" - import { LoadingButton } from "../buttons" - import SocialSignOnButtons from "components/auth/SocialSignOnButtons" - import Divider from "../Divider/Divider" +import { useRouter } from "next/router" +import { + useSignInWithEmailAndPassword, + SignInWithEmailAndPasswordData +} from "../auth/hooks" +import { Form, Stack, Alert, Container, Row, Col, Card } from "../bootstrap" +import Input from "../forms/Input" +import PasswordInput from "../forms/PasswordInput" +import { useTranslation } from "next-i18next" +import { LoadingButton } from "../buttons" +import SocialSignOnButtons from "components/auth/SocialSignOnButtons" +import Divider from "../Divider/Divider" - export default function Login() { - const router = useRouter() - const redirect = (router.query.redirect as string) || "/" - console.log(redirect); - - const { t } = useTranslation("auth") +export default function Login() { + const router = useRouter() + const redirect = (router.query.redirect as string) || "/" + const { t } = useTranslation("auth") - const { - register, - handleSubmit, - formState: { errors } - } = useForm() + const { + register, + handleSubmit, + formState: { errors } + } = useForm() - const signIn = useSignInWithEmailAndPassword() + const signIn = useSignInWithEmailAndPassword() - const success = () => { - const safeRedirect = redirect.startsWith("/") ? redirect : "/" - router.replace(safeRedirect) - } - const onSubmit = handleSubmit(credentials => { - signIn.execute(credentials).then(success) - }) + const success = () => { + const safeRedirect = redirect.startsWith("/") ? redirect : "/" + router.replace(safeRedirect) + } + const onSubmit = handleSubmit(credentials => { + signIn.execute(credentials).then(success) + }) - return ( - - - - -

{t("signInToAccess")}

+ return ( + + + + +

{t("signInToAccess")}

-
- {signIn.error && ( - {signIn.error.message} - )} + + {signIn.error && ( + {signIn.error.message} + )} - - + + - + - - {t("signIn")} - + + {t("signIn")} + - {t("or")} + {t("or")} - router.replace(redirect)} - /> - - -
- -
-
- ) - } \ No newline at end of file + router.replace(redirect)} + /> + + +
+ +
+
+ ) +} diff --git a/components/Newsfeed/Newsfeed.tsx b/components/Newsfeed/Newsfeed.tsx index 4b9904d89..4ffeb4397 100644 --- a/components/Newsfeed/Newsfeed.tsx +++ b/components/Newsfeed/Newsfeed.tsx @@ -14,7 +14,7 @@ import { StyledContainer } from "./StyledNewsfeedComponents" import ProfileSettingsModal from "components/EditProfilePage/ProfileSettingsModal" -import LoginPage from "components/Login/login" +import LoginPage from "components/Login/Login" import { NewsfeedCard } from "components/NewsfeedCard/NewsfeedCard" import { ProfileButtons } from "components/ProfilePage/ProfileButtons" diff --git a/pages/edit-profile/[[...docName]].tsx b/pages/edit-profile/[[...docName]].tsx index 68afe0970..4832b1a3d 100644 --- a/pages/edit-profile/[[...docName]].tsx +++ b/pages/edit-profile/[[...docName]].tsx @@ -14,11 +14,10 @@ const Query = z.object({ export default createPage({ title: "Edit Profile", - Page: () => { - // Page: requireAuth(({ user }) => { + Page: requireAuth(() => { const tabTitle = Query.parse(useRouter().query).docName?.[0] || "about-you" return - } + }) }) export const getStaticPaths: GetStaticPaths = async ctx => { diff --git a/pages/login.tsx b/pages/login.tsx index 71bbe2b91..9ad67a3f8 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -1,5 +1,5 @@ import { createPage } from "../components/page" -import Login from "components/Login/login" +import Login from "components/Login/Login" export default createPage({ title: "Login", From 3ba84b5f00b7ac2ae31f8b84fc1577f56b9d70fd Mon Sep 17 00:00:00 2001 From: huanfeng Date: Wed, 30 Jul 2025 09:14:29 +0800 Subject: [PATCH 6/9] Rename Login.tsx --- components/Login/Login.tsx | 13 +----- components/Login/login.tsx | 86 ------------------------------------- public/locales/en/auth.json | 2 +- 3 files changed, 3 insertions(+), 98 deletions(-) delete mode 100644 components/Login/login.tsx diff --git a/components/Login/Login.tsx b/components/Login/Login.tsx index 3c2c55876..9387ad03a 100644 --- a/components/Login/Login.tsx +++ b/components/Login/Login.tsx @@ -4,16 +4,7 @@ import { useSignInWithEmailAndPassword, SignInWithEmailAndPasswordData } from "../auth/hooks" -import { - Form, - Stack, - Button, - Alert, - Container, - Row, - Col, - Card -} from "../bootstrap" +import { Form, Stack, Alert, Container, Row, Col, Card } from "../bootstrap" import Input from "../forms/Input" import PasswordInput from "../forms/PasswordInput" import { useTranslation } from "next-i18next" @@ -47,7 +38,7 @@ export default function Login() { -

{t("signInToAccess")}

+

{t("signInToAccess")}

{signIn.error && ( diff --git a/components/Login/login.tsx b/components/Login/login.tsx deleted file mode 100644 index f68a9dfa3..000000000 --- a/components/Login/login.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useForm } from "react-hook-form" -import { useRouter } from "next/router" -import { - useSignInWithEmailAndPassword, - SignInWithEmailAndPasswordData -} from "../auth/hooks" -import { Form, Stack, Alert, Container, Row, Col, Card } from "../bootstrap" -import Input from "../forms/Input" -import PasswordInput from "../forms/PasswordInput" -import { useTranslation } from "next-i18next" -import { LoadingButton } from "../buttons" -import SocialSignOnButtons from "components/auth/SocialSignOnButtons" -import Divider from "../Divider/Divider" - -export default function Login() { - const router = useRouter() - const redirect = (router.query.redirect as string) || "/" - const { t } = useTranslation("auth") - - const { - register, - handleSubmit, - formState: { errors } - } = useForm() - - const signIn = useSignInWithEmailAndPassword() - - const success = () => { - const safeRedirect = redirect.startsWith("/") ? redirect : "/" - router.replace(safeRedirect) - } - const onSubmit = handleSubmit(credentials => { - signIn.execute(credentials).then(success) - }) - - return ( - - - - -

{t("signInToAccess")}

- - - {signIn.error && ( - {signIn.error.message} - )} - - - - - - - - {t("signIn")} - - - {t("or")} - - router.replace(redirect)} - /> - - -
- -
-
- ) -} diff --git a/public/locales/en/auth.json b/public/locales/en/auth.json index 8808cd946..52b4557d1 100644 --- a/public/locales/en/auth.json +++ b/public/locales/en/auth.json @@ -57,5 +57,5 @@ "setUpProfile": "Set Up Your Profile", "probablySignedOut": "You were possibly signed out while trying to go to a page that needs to be signed in to function", "pleaseConsider": "Please consider logging in first:", - "signInToAccess": "Login required to access the contents" + "signInToAccess": "Login required to access the content" } \ No newline at end of file From 0288e0f4f6a60d4de296f227da8cfaf3ad7a203a Mon Sep 17 00:00:00 2001 From: huanfeng Date: Thu, 14 Aug 2025 23:05:39 +0800 Subject: [PATCH 7/9] Migrate to i18n-based title --- components/Login/login.tsx | 120 ++++++++++++++++++++++------------ next-env.d.ts | 2 +- pages/login.tsx | 2 +- public/locales/en/common.json | 3 +- 4 files changed, 82 insertions(+), 45 deletions(-) diff --git a/components/Login/login.tsx b/components/Login/login.tsx index 820d49590..9387ad03a 100644 --- a/components/Login/login.tsx +++ b/components/Login/login.tsx @@ -1,50 +1,86 @@ +import { useForm } from "react-hook-form" +import { useRouter } from "next/router" +import { + useSignInWithEmailAndPassword, + SignInWithEmailAndPasswordData +} from "../auth/hooks" +import { Form, Stack, Alert, Container, Row, Col, Card } from "../bootstrap" +import Input from "../forms/Input" +import PasswordInput from "../forms/PasswordInput" import { useTranslation } from "next-i18next" -import styled from "styled-components" -import { Container } from "../bootstrap" -import { SignInWithButton } from "components/auth" +import { LoadingButton } from "../buttons" +import SocialSignOnButtons from "components/auth/SocialSignOnButtons" +import Divider from "../Divider/Divider" -export default function LoginPage() { +export default function Login() { + const router = useRouter() + const redirect = (router.query.redirect as string) || "/" const { t } = useTranslation("auth") - const StyledContainer = styled(Container)` - @media (min-width: 768px) { - } - ` + const { + register, + handleSubmit, + formState: { errors } + } = useForm() + + const signIn = useSignInWithEmailAndPassword() + + const success = () => { + const safeRedirect = redirect.startsWith("/") ? redirect : "/" + router.replace(safeRedirect) + } + const onSubmit = handleSubmit(credentials => { + signIn.execute(credentials).then(success) + }) return ( - -
-
-
-
-
- closed lock with key{" "} -
- {t("almostThere")} -
-
-
- {t("justLogIn")} -
-
-
- -
-
-
-
-
-
+ + + + +

{t("signInToAccess")}

+ +
+ {signIn.error && ( + {signIn.error.message} + )} + + + + + + + + {t("signIn")} + + + {t("or")} + + router.replace(redirect)} + /> + +
+
+ +
+
) } diff --git a/next-env.d.ts b/next-env.d.ts index a4a7b3f5c..4f11a03dc 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/pages/login.tsx b/pages/login.tsx index 9ad67a3f8..a0f478205 100644 --- a/pages/login.tsx +++ b/pages/login.tsx @@ -2,7 +2,7 @@ import { createPage } from "../components/page" import Login from "components/Login/Login" export default createPage({ - title: "Login", + titleI18nKey: "navigation.login", Page: () => }) import { serverSideTranslations } from "next-i18next/serverSideTranslations" diff --git a/public/locales/en/common.json b/public/locales/en/common.json index eab8fbaf4..789009ed4 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -79,7 +79,8 @@ "supportMaple": "Support MAPLE", "aboutTestimony": "About Testimony", "viewProfile": "View Profile", - "whyUseMaple": "Why Use MAPLE" + "whyUseMaple": "Why Use MAPLE", + "login": "Login" }, "newcomer": "New to MAPLE? For extra support, check", "newsletter": "Click Here to Subscribe to Our Newsletter", From 92a77c418b3007b0db52091acdd22032989cdc62 Mon Sep 17 00:00:00 2001 From: huanfeng Date: Thu, 14 Aug 2025 23:15:43 +0800 Subject: [PATCH 8/9] Fix the login/Login file conflic --- components/Login/Login.tsx | 2 +- components/Login/login.tsx | 86 -------------------------------------- 2 files changed, 1 insertion(+), 87 deletions(-) delete mode 100644 components/Login/login.tsx diff --git a/components/Login/Login.tsx b/components/Login/Login.tsx index 9387ad03a..b4b187a1b 100644 --- a/components/Login/Login.tsx +++ b/components/Login/Login.tsx @@ -83,4 +83,4 @@ export default function Login() {
) -} +} \ No newline at end of file diff --git a/components/Login/login.tsx b/components/Login/login.tsx deleted file mode 100644 index 9387ad03a..000000000 --- a/components/Login/login.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useForm } from "react-hook-form" -import { useRouter } from "next/router" -import { - useSignInWithEmailAndPassword, - SignInWithEmailAndPasswordData -} from "../auth/hooks" -import { Form, Stack, Alert, Container, Row, Col, Card } from "../bootstrap" -import Input from "../forms/Input" -import PasswordInput from "../forms/PasswordInput" -import { useTranslation } from "next-i18next" -import { LoadingButton } from "../buttons" -import SocialSignOnButtons from "components/auth/SocialSignOnButtons" -import Divider from "../Divider/Divider" - -export default function Login() { - const router = useRouter() - const redirect = (router.query.redirect as string) || "/" - const { t } = useTranslation("auth") - - const { - register, - handleSubmit, - formState: { errors } - } = useForm() - - const signIn = useSignInWithEmailAndPassword() - - const success = () => { - const safeRedirect = redirect.startsWith("/") ? redirect : "/" - router.replace(safeRedirect) - } - const onSubmit = handleSubmit(credentials => { - signIn.execute(credentials).then(success) - }) - - return ( - - - - -

{t("signInToAccess")}

- -
- {signIn.error && ( - {signIn.error.message} - )} - - - - - - - - {t("signIn")} - - - {t("or")} - - router.replace(redirect)} - /> - -
-
- -
-
- ) -} From 9aae6010b20403fe6d6e0b1712bfaf2f1b8fb479 Mon Sep 17 00:00:00 2001 From: huanfeng Date: Thu, 14 Aug 2025 23:20:38 +0800 Subject: [PATCH 9/9] Run prettier --- components/Login/Login.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Login/Login.tsx b/components/Login/Login.tsx index b4b187a1b..9387ad03a 100644 --- a/components/Login/Login.tsx +++ b/components/Login/Login.tsx @@ -83,4 +83,4 @@ export default function Login() { ) -} \ No newline at end of file +}