Skip to content

Commit

Permalink
Merge pull request #188 from JohnsonMao/feature/signin-page-success-m…
Browse files Browse the repository at this point in the history
…odal

feature: verified success modal
  • Loading branch information
JohnsonMao authored Dec 21, 2024
2 parents 22771cf + f9a0a67 commit c3ab188
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 72 deletions.
4 changes: 2 additions & 2 deletions components/Profile/Edit/useEditProfile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ const useEditProfile = () => {
isFocus = true;

if (['INPUT', 'TEXTAREA'].includes(element.tagName)) {
element.focus();
element?.focus?.();
} else {
element.scrollIntoView({ block: 'center' });
element?.scrollIntoView?.({ block: 'center' });
}
}
return [err.path[0], err.message];
Expand Down
26 changes: 11 additions & 15 deletions contexts/Auth/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ const authReducer = (state: AuthState, action: Action): AuthState => {
return initialState;
}
if (action.payload) {
const reminder = getReminderStorage().get();
getReminderStorage().set(
typeof reminder === "number" ? reminder + 1 : 1
);
return {
...state,
isComplete: checkIsComplete(action.payload),
Expand Down Expand Up @@ -229,7 +225,7 @@ export function AuthProvider({ children }: PropsWithChildren) {
);

useEffect(() => {
const handleToken = (token: string) => {
const handleToken = (token?: string) => {
if (!token) return;
// TODO: 待移除 redux,為了同步資訊
reduxDispatch(fetchUserByToken(token));
Expand Down Expand Up @@ -271,12 +267,17 @@ export function AuthProvider({ children }: PropsWithChildren) {
switch (state.loginStatus) {
case LoginStatus.TEMPORARY: {
const redirectUrl = state.redirectUrl || getRedirectionStorage().get();
getReminderStorage().remove();
authDispatch.closeLoginModal();
router.replace(redirectUrl || "/signin");
break;
}
case LoginStatus.PERMANENT: {
const redirectUrl = state.redirectUrl || getRedirectionStorage().get();
const reminder = getReminderStorage().get();
getReminderStorage().set(
typeof reminder === "number" ? reminder + 1 : 1
);
authDispatch.closeLoginModal();
if (redirectUrl) router.replace(redirectUrl);
break;
Expand All @@ -293,8 +294,9 @@ export function AuthProvider({ children }: PropsWithChildren) {

useEffect(() => {
const redirectionStorage = getRedirectionStorage();
const redirection = redirectionStorage.get();

if (redirectionStorage.get() === pathname) {
if (redirection?.split("?")[0] === pathname) {
redirectionStorage.remove();
}
}, [pathname]);
Expand Down Expand Up @@ -363,11 +365,6 @@ export const ProtectedComponent = ({
};

export const sendLoginEvent = (token: string) => {
if (!token) {
// TODO: 處理沒 token 的狀況
return;
}

getTokenStorage().remove();

if (
Expand All @@ -379,9 +376,8 @@ export const sendLoginEvent = (token: string) => {
window.location.origin
);
window.close();
} else {
const redirection = getRedirectionStorage().get();
getTokenStorage().set(token);
window.location.replace(redirection || "/");
return true;
}

return false;
};
8 changes: 7 additions & 1 deletion pages/404.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import styled from '@emotion/styled';
import Box from '@mui/material/Box';
import { Typography, Button, Paper } from '@mui/material';
Expand All @@ -10,13 +10,19 @@ import Footer from '../shared/components/Footer_v2';
import { COLOR_TABLE } from '../constants/notion';
import { CATEGORIES } from '../constants/category';
import RelatedResources from '../shared/components/RelatedResources';
import { getRedirectionStorage } from '@/utils/storage';

const BodyWrapper = styled.div`
background-color: #f5f5f5;
`;

const NotExistPage = () => {
const router = useRouter();

useEffect(() => {
getRedirectionStorage().remove();
}, []);

return (
<Paper
sx={{
Expand Down
78 changes: 73 additions & 5 deletions pages/_app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import CssBaseline from '@mui/material/CssBaseline';
import { Toaster } from 'react-hot-toast';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { useRouter } from 'next/router';
import { useSearchParams } from 'next/navigation';
import Script from 'next/script';
import Head from 'next/head';
import { persistStore } from 'redux-persist';
Expand All @@ -13,6 +14,8 @@ import { AuthProvider, useAuth } from '@/contexts/Auth';
import SnackbarProvider from '@/contexts/Snackbar';
import CompleteInfoReminderDialog from '@/shared/components/CompleteInfoReminderDialog';
import GlobalStyle from '@/shared/styles/Global';
import Image from "@/shared/components/Image";
import Modal from '@/shared/components/Modal';
import themeFactory from '@/shared/styles/themeFactory';
import storeFactory from '@/redux/store';
import { checkLoginValidity } from '@/redux/actions/user';
Expand Down Expand Up @@ -116,15 +119,18 @@ const App = ({ Component, pageProps }) => {

const ThemeComponentWrap = ({ pageProps, Component }) => {
const dispatch = useDispatch();
const searchParams = useSearchParams();
const router = useRouter();
const mode = useSelector((state) => state?.theme?.mode ?? 'light');
const theme = useMemo(() => themeFactory(mode), [mode]);
const isEnv = useMemo(() => process.env.NODE_ENV === 'development', []);
const { isComplete, isLoggedIn } = useAuth();
const [isOpen, setIsOpen] = useState(false);
const [openModalType, setOpenModalType] = useState(null);
const Layout = Component?.getLayout || DefaultLayout;
const isVerified = searchParams.get("isVerified");

const handleClose = () => {
setIsOpen(false);
setOpenModalType(null);
getReminderStorage().remove();
};

Expand All @@ -133,10 +139,15 @@ const ThemeComponentWrap = ({ pageProps, Component }) => {
}, []);

useEffect(() => {
if (isVerified) {
setOpenModalType("verifiedSuccess");
return;
}

if (isLoggedIn && !isComplete && getReminderStorage().get() % 3 === 0) {
setIsOpen(true);
setOpenModalType("completeInfoReminder");
}
}, [isLoggedIn, isComplete]);
}, [isVerified, isLoggedIn, isComplete]);

return (
<ThemeProvider theme={theme}>
Expand All @@ -159,7 +170,64 @@ const ThemeComponentWrap = ({ pageProps, Component }) => {
}}
/>
{isEnv && <Mode />}
<CompleteInfoReminderDialog isOpen={isOpen} onClose={handleClose} />
<CompleteInfoReminderDialog isOpen={openModalType === "completeInfoReminder"} onClose={handleClose} />
<Modal
isOpen={openModalType === 'verifiedSuccess' && isLoggedIn}
onClose={handleClose}
title="驗證成功"
describedby="verifiedSuccess"
>
<Image
src="/assets/illustration.png"
alt="verified-success"
width="300"
height="289"
/>
<p id="verifiedSuccess" className="mb-6 text-center text-basic-400 body-sm">
{
isComplete ?
<span>
帳號已驗證成功,快來體驗平台的特色功能!
</span>
:
<span>
我們會公開你的<strong className="font-bold">個人檔案</strong>,填寫完整的資料,才能讓其他夥伴們更了解你喔!
</span>
}
</p>
<div className="flex gap-2">
{
isComplete ?
<button
type="button"
className="flex-1 py-2 shadow-lg transition-colors rounded-full bg-primary-base text-white hover:bg-primary-darker"
onClick={handleClose}
>
開始探索
</button>
:
<>
<button
type="button"
className="flex-1 py-2 shadow-lg transition-colors rounded-full bg-white text-primary-darker hover:bg-basic-100"
onClick={handleClose}
>
暫時不需要
</button>
<button
type="button"
className="flex-1 py-2 shadow-lg transition-colors rounded-full bg-primary-base text-white hover:bg-primary-darker"
onClick={() => {
handleClose();
router.replace('/profile')
}}
>
想,填寫資料
</button>
</>
}
</div>
</Modal>
<Layout>
<Component {...pageProps} />
</Layout>
Expand Down
49 changes: 0 additions & 49 deletions pages/auth/callback/index.jsx

This file was deleted.

42 changes: 42 additions & 0 deletions pages/auth/callback/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { useDispatch } from "react-redux";
import { sendLoginEvent, useAuthDispatch } from "@/contexts/Auth";
import { getRedirectionStorage } from "@/utils/storage";
import { fetchUserByToken } from "@/redux/actions/user";
import Image from "@/shared/components/Image";

export default function AuthCallbackPage() {
// TODO: 待移除 redux,為了同步資訊
const reduxDispatch = useDispatch();
const authDispatch = useAuthDispatch();
const router = useRouter();
const searchParams = useSearchParams();
const token = searchParams.get("token");
const isVerified = searchParams.get("isVerified");

useEffect(() => {
if (!token) return;
if (sendLoginEvent(token)) return;

reduxDispatch(fetchUserByToken(token));
authDispatch.setToken(token);
router.replace(getRedirectionStorage().get() || "/");
}, [token, isVerified, router.replace]);

return (
<div className="w-11/12 mx-auto my-5 p-5 min-h-[60vh] shadow-lg rounded-lg border border-solid border-basic-100">
<h2 className="text-center text-3xl font-bold tracking-[0.08em] text-basic-400">
正在前往新的島嶼
</h2>
<div className="flex justify-center items-center">
<Image
src="/assets/nobody-land.gif"
alt="nobody-land"
width="300"
height="300"
/>
</div>
</div>
);
}

0 comments on commit c3ab188

Please sign in to comment.