From 750252f8509ed9dcad397fd66522b6f23e1d665e Mon Sep 17 00:00:00 2001 From: VincentXu <90778107+vincentxuu@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:59:48 +0800 Subject: [PATCH 1/2] adjust the description (#90) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix:adjust value of options (#86) 修正以下: 1.刪除高中以下學歷選項 2.刪除交友相關字眼,並新增選項 3.調整揪團教育階段敘述 4.調整學歷敘述 5.調整性別敘述 * Fix/adjust options (#89) * fix:adjust value of options * fix:adjust value of rule --- components/Group/Form/useGroupForm.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Group/Form/useGroupForm.jsx b/components/Group/Form/useGroupForm.jsx index fd2bc81..f18a272 100644 --- a/components/Group/Form/useGroupForm.jsx +++ b/components/Group/Form/useGroupForm.jsx @@ -47,7 +47,7 @@ const rules = { partnerStyle: z.string().max(50, '請勿輸入超過 50 字'), partnerEducationStep: z .array(z.enum(eduOptions.map(({ label }) => label))) - .min(1, '請選擇的學習階段'), + .min(1, '請選擇適合的學習階段'), description: z .string() .min(1, '請輸入揪團描述') From 6fbc3b9eebaef5e42502e4a9407e2e77dfe0df31 Mon Sep 17 00:00:00 2001 From: VincentXu <90778107+vincentxuu@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:00:37 +0800 Subject: [PATCH 2/2] fix group page (#92) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix:adjust value of options (#86) 修正以下: 1.刪除高中以下學歷選項 2.刪除交友相關字眼,並新增選項 3.調整揪團教育階段敘述 4.調整學歷敘述 5.調整性別敘述 * Fix/adjust options (#89) * fix:adjust value of options * fix:adjust value of rule * feat: optimize login flow (#91) * fix: adjust shareButtonGroup position (#88) --------- Co-authored-by: Johnson Mao <86179381+JohnsonMao@users.noreply.github.com> Co-authored-by: ruby10127130 <52684045+ruby10127130@users.noreply.github.com> --- components/Group/Form/index.jsx | 15 +- components/Group/Form/useGroupForm.jsx | 9 +- components/Group/detail/Contact/index.jsx | 14 +- components/Group/detail/index.jsx | 14 +- pages/_app.jsx | 27 ++- pages/index.jsx | 15 +- pages/login/index.jsx | 32 ++-- pages/login/popup/index.jsx | 158 ++++++++++++++++++ .../MainNav/Hamberger/MenuList.jsx | 8 +- .../Navigation_v2/MainNav/SubList/index.jsx | 6 +- shared/components/Navigation_v2/index.jsx | 2 +- utils/openLoginWindow.js | 15 ++ utils/share.js | 2 +- utils/storage.js | 19 +++ 14 files changed, 281 insertions(+), 55 deletions(-) create mode 100644 pages/login/popup/index.jsx create mode 100644 utils/openLoginWindow.js create mode 100644 utils/storage.js diff --git a/components/Group/Form/index.jsx b/components/Group/Form/index.jsx index 63061b0..ab635d7 100644 --- a/components/Group/Form/index.jsx +++ b/components/Group/Form/index.jsx @@ -24,8 +24,15 @@ export default function GroupForm({ isLoading, onSubmit, }) { - const { control, values, errors, isDirty, setValues, handleSubmit } = - useGroupForm(); + const { + notLogin, + control, + values, + errors, + isDirty, + setValues, + handleSubmit, + } = useGroupForm(); const isCreateMode = mode === 'create'; useEffect(() => { @@ -36,6 +43,10 @@ export default function GroupForm({ }); }, [defaultValues]); + if (notLogin) { + return ; + } + return ( diff --git a/components/Group/Form/useGroupForm.jsx b/components/Group/Form/useGroupForm.jsx index f18a272..502ae9f 100644 --- a/components/Group/Form/useGroupForm.jsx +++ b/components/Group/Form/useGroupForm.jsx @@ -1,11 +1,11 @@ import { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { useRouter } from 'next/router'; import { ZodType, z } from 'zod'; import { CATEGORIES } from '@/constants/category'; import { AREAS } from '@/constants/areas'; import { EDUCATION_STEP } from '@/constants/member'; import { BASE_URL } from '@/constants/common'; +import openLoginWindow from '@/utils/openLoginWindow'; const _eduOptions = EDUCATION_STEP.filter( (edu) => !['master', 'doctor', 'other'].includes(edu.value), @@ -57,9 +57,9 @@ const rules = { }; export default function useGroupForm() { - const router = useRouter(); const [isDirty, setIsDirty] = useState(false); const me = useSelector((state) => state.user); + const notLogin = !me?._id; const [values, setValues] = useState({ ...DEFAULT_VALUES, userId: me?._id, @@ -143,10 +143,11 @@ export default function useGroupForm() { }; useEffect(() => { - if (!me?._id) router.push('/login'); - }, [me, router]); + if (notLogin) openLoginWindow('/login'); + }, [notLogin]); return { + notLogin, control, errors, values, diff --git a/components/Group/detail/Contact/index.jsx b/components/Group/detail/Contact/index.jsx index 69e3524..5d8934a 100644 --- a/components/Group/detail/Contact/index.jsx +++ b/components/Group/detail/Contact/index.jsx @@ -1,7 +1,6 @@ import { useId, useState, forwardRef, useEffect } from 'react'; import { useRouter } from 'next/router'; import { useSelector } from 'react-redux'; -import Link from 'next/link'; import styled from '@emotion/styled'; import { Avatar, @@ -20,6 +19,7 @@ import { ROLE } from '@/constants/member'; import chatSvg from '@/public/assets/icons/chat.svg'; import useMutation from '@/hooks/useMutation'; import { mapToTable } from '@/utils/helper'; +import openLoginWindow from '@/utils/openLoginWindow'; import Feedback from './Feedback'; const ROLELIST = mapToTable(ROLE); @@ -55,17 +55,18 @@ const StyledTextArea = styled(TextareaAutosize)` width: 100%; min-height: 128px; `; -const StyledLink = styled(Link)` +const StyledText = styled.div` margin-top: 6px; margin-left: 6px; display: block; color: black; font-size: 12px; `; -const StyledSpan = styled.span` +const StyledLink = styled.span` padding: 0 2px; color: #16b9b3; text-decoration: underline; + cursor: pointer; `; const Transition = forwardRef((props, ref) => { @@ -152,10 +153,11 @@ function ContactButton({ {label} {!isLogin && ( - - 註冊登入 + + router.push('/login')}>註冊或 + openLoginWindow()}>登入 即可聯繫主揪! - + )} 已結束 )} - {isMyGroup ? ( )} + + + {isLoading ? : source?.title} diff --git a/pages/_app.jsx b/pages/_app.jsx index 8697a18..6604fc8 100644 --- a/pages/_app.jsx +++ b/pages/_app.jsx @@ -6,14 +6,14 @@ import { Provider, useDispatch, useSelector } from 'react-redux'; import { useRouter } from 'next/router'; import Script from 'next/script'; import Head from 'next/head'; -import { initializeApp } from 'firebase/app'; import { persistStore } from 'redux-persist'; import { PersistGate } from 'redux-persist/integration/react'; import SnackbarProvider from '@/contexts/Snackbar'; import GlobalStyle from '@/shared/styles/Global'; import themeFactory from '@/shared/styles/themeFactory'; import storeFactory from '@/redux/store'; -import { checkLoginValidity } from '@/redux/actions/user'; +import { checkLoginValidity, fetchUserById } from '@/redux/actions/user'; +import { getRedirectionStorage } from '@/utils/storage'; import { initGA, logPageView } from '../utils/analytics'; import Mode from '../shared/components/Mode'; import 'regenerator-runtime/runtime'; // Speech.js @@ -112,15 +112,36 @@ const App = ({ Component, pageProps }) => { const ThemeComponentWrap = ({ pageProps, Component }) => { const dispatch = useDispatch(); - const firebaseApp = initializeApp(firebaseConfig); const mode = useSelector((state) => state?.theme?.mode ?? 'light'); const theme = useMemo(() => themeFactory(mode), [mode]); const isEnv = useMemo(() => process.env.NODE_ENV === 'development', []); + const router = useRouter(); useEffect(() => { dispatch(checkLoginValidity()); }, []); + useEffect(() => { + const receiveMessage = (e) => { + if (e.origin !== window.location.origin) return; + if (e.data.isLogin) { + const { token, id } = e.data; + const redirectionStorage = getRedirectionStorage(); + const redirection = redirectionStorage.get(); + dispatch(fetchUserById(id, token)); + if (redirection) { + redirectionStorage.remove(); + router.push(redirection); + } + } + }; + window.addEventListener('message', receiveMessage, false); + + return () => { + window.removeEventListener('message', receiveMessage, false); + }; + }, []); + return ( {/* mui normalize css */} diff --git a/pages/index.jsx b/pages/index.jsx index b132474..2e3f97d 100644 --- a/pages/index.jsx +++ b/pages/index.jsx @@ -1,8 +1,6 @@ import React, { useMemo, useEffect } from 'react'; import styled from '@emotion/styled'; import { useRouter } from 'next/router'; -import { useDispatch, useSelector } from 'react-redux'; -import { fetchUserById } from '@/redux/actions/user'; import SEOConfig from '../shared/components/SEO'; import Home from '../components/Home'; import Navigation from '../shared/components/Navigation_v2'; @@ -47,14 +45,15 @@ const HomePage = () => { [router?.asPath], ); - // fetch signin userData with token and id from query String - - const dispatch = useDispatch(); const { token, id } = router.query; + useEffect(() => { - if (token) { - dispatch(fetchUserById(id, token)); - router.push('/'); + if (id && token) { + window.opener?.postMessage( + { isLogin: true, id, token }, + window.location.origin, + ); + window.close(); } }, [id, token]); diff --git a/pages/login/index.jsx b/pages/login/index.jsx index b235006..45f8e3c 100644 --- a/pages/login/index.jsx +++ b/pages/login/index.jsx @@ -1,7 +1,6 @@ import React, { useMemo } from 'react'; import styled from '@emotion/styled'; import { useRouter } from 'next/router'; -import Link from '@mui/material/Link'; import Script from 'next/script'; import { Box, Typography, Button, Skeleton } from '@mui/material'; import { LazyLoadImage } from 'react-lazy-load-image-component'; @@ -9,6 +8,7 @@ import SEOConfig from '@/shared/components/SEO'; import Navigation from '@/shared/components/Navigation_v2'; import Footer from '@/shared/components/Footer_v2'; import { BASE_URL } from '@/constants/common'; +import openLoginWindow from '@/utils/openLoginWindow'; // import sendDataToChromeExtension from '../../utils/sendDataToChromeExtension'; const HomePageWrapper = styled.div` @@ -38,7 +38,7 @@ const ContentWrapper = styled.div` `; const LoginPage = () => { - const LOGINPATH = `${BASE_URL}/auth/google`; + const LOGIN_PATH = `${BASE_URL}/auth/google`; const router = useRouter(); const SEOData = useMemo( @@ -101,21 +101,19 @@ const LoginPage = () => { /> } /> - - - + {`註冊即代表您同意島島阿學的 `} diff --git a/pages/login/popup/index.jsx b/pages/login/popup/index.jsx new file mode 100644 index 0000000..c1a5786 --- /dev/null +++ b/pages/login/popup/index.jsx @@ -0,0 +1,158 @@ +import React, { useMemo } from 'react'; +import styled from '@emotion/styled'; +import { useRouter } from 'next/router'; +import Link from '@mui/material/Link'; +import Script from 'next/script'; +import { Box, Typography, Button, Skeleton } from '@mui/material'; +import { LazyLoadImage } from 'react-lazy-load-image-component'; +import SEOConfig from '@/shared/components/SEO'; +import { NavigationWrapper } from '@/shared/components/Navigation_v2'; +import { BASE_URL } from '@/constants/common'; +import Logo from '@/shared/components/Navigation_v2/MainNav/Logo'; + +const HomePageWrapper = styled.div` + --section-height: calc(100vh - 80px); + --section-height-offset: 80px; + background: linear-gradient(0deg, #f3fcfc, #f3fcfc), #f7f8fa; +`; + +const ContentWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #fff; + border-radius: 8px; + margin: 60px auto; + padding: 40px 40px; + max-width: 440px; + width: 100%; + @media (max-width: 767px) { + width: 90%; + .title { + text-overflow: ellipsis; + width: 100%; + } + } +`; + +const LoginPage = () => { + const LOGINPATH = `${BASE_URL}/auth/google`; + const router = useRouter(); + + const SEOData = useMemo( + () => ({ + title: '登入島島|島島阿學', + description: + '「島島阿學」盼能透過建立多元的學習資源網絡,讓自主學習者能找到合適的成長方法,進一步成為自己想成為的人,從中培養共好精神。目前正積極打造「可共編的學習資源平台」。', + keywords: '島島阿學', + author: '島島阿學', + copyright: '島島阿學', + imgLink: 'https://www.daoedu.tw/preview.webp', + link: `${process.env.HOSTNAME}${router?.asPath}`, + }), + [router?.asPath], + ); + + return ( + <> +