diff --git a/apps/sso/components/reset-card/reset-email-card.tsx b/apps/sso/components/reset-card/reset-email-card.tsx index 213f1dc3..032133d2 100644 --- a/apps/sso/components/reset-card/reset-email-card.tsx +++ b/apps/sso/components/reset-card/reset-email-card.tsx @@ -10,6 +10,7 @@ import { useHibiscusSupabase } from '@hibiscus/hibiscus-supabase-context'; import { Button, ColorSpanBold } from '@hibiscus/ui-kit-2023'; import { StyledAuthCard } from '../auth-components/styled-card'; import { Input } from '../auth-components/styled-input'; +import { useRouter } from 'next/router'; /* eslint-disable-next-line */ export interface ResetCardProps {} @@ -18,6 +19,8 @@ export function ResetEmailCard(props: ResetCardProps) { const [hideSuccessMessage, setHideSuccessMessage] = useState(false); const { supabase } = useHibiscusSupabase(); + const router = useRouter(); + async function handleSubmit(event) { event.preventDefault(); @@ -30,6 +33,7 @@ export function ResetEmailCard(props: ResetCardProps) { alert(error); } else { setHideSuccessMessage(true); + router.push(`/reset-verify?email=${email}`); } } diff --git a/apps/sso/components/routeGuard.tsx b/apps/sso/components/routeGuard.tsx index 0084ffc1..aa621534 100644 --- a/apps/sso/components/routeGuard.tsx +++ b/apps/sso/components/routeGuard.tsx @@ -31,7 +31,7 @@ export function RouteGuard({ children }) { '/reset', '/reset#', '/reset-email', - '/reset-redirect', + '/reset-verify', ]; const path = url.split('?')[0]; diff --git a/apps/sso/components/verify-card/reset-verify-card.tsx b/apps/sso/components/verify-card/reset-verify-card.tsx new file mode 100644 index 00000000..2f0372e9 --- /dev/null +++ b/apps/sso/components/verify-card/reset-verify-card.tsx @@ -0,0 +1,137 @@ +import styled from 'styled-components'; +import { H3, ItalicText, Text } from '@hibiscus/ui'; +import { Colors2023 } from '@hibiscus/styles'; +import OTPInput from '../otp-input/otp-input'; +import { useState } from 'react'; +import { useRouter } from 'next/router'; +import { HibiscusSupabaseClient } from '@hibiscus/hibiscus-supabase-client'; +import Image from 'next/image'; +import { MutatingDots } from 'react-loader-spinner'; +import { Button } from '@hibiscus/ui-kit-2023'; +import { useHibiscusSupabase } from '@hibiscus/hibiscus-supabase-context'; + +export function ResetVerifyCard() { + const router = useRouter(); + const { supabase } = useHibiscusSupabase(); + const [verifyState, setVerifyState] = useState(''); + const [hideErrorMessage, setHideErrorMessage] = useState(false); + const [code, setCode] = useState(''); + const [pinReady, setPinReady] = useState(false); + const MAX_CODE_LENGTH = 6; + + const handleOTP = async () => { + const email = String(router.query.email); + + const { data, error } = await supabase.verifyOtp(email, code, 'recovery'); + + if (error) { + console.log(error); + setHideErrorMessage(true); + } + if (data.user) { + setVerifyState('verifying'); + + HibiscusSupabaseClient.setTokenCookieClientSide( + data.session.access_token, + data.session.refresh_token + ); + + router.push('/reset'); + } + }; + + const handleKeyDown = (e) => { + //it triggers by pressing the enter key + console.log(e.target.value); + if (e.keyCode === 13) { + handleOTP(); + } + }; + + return ( + + HackSC Logo + + We've sent you an email containing a unique 6-digit PIN code. + + + This email may take up to 2 minutes to arrive. Do not share this code + with anyone else. + + + + Token is expired or incorrect. + + + + If you did not receive your email, please sign up again + + {verifyState === 'verifying' ? ( + + ) : ( + '' + )} + + ); +} + +export default ResetVerifyCard; + +const StyledVerifyCard = styled.div` + min-width: 55vw; + max-width: 90vw; + padding: 5rem 2rem; + display: flex; + flex-direction: column; + margin: auto; + align-items: center; + border-radius: 20px; + border: 5px solid ${Colors2023.BLUE.STANDARD}; + box-shadow: 0px 0px 10px ${Colors2023.BLUE.LIGHT}; + gap: 15px; + > p { + text-align: center; + } + @media (max-width: 400px) { + padding: 2rem; + } +`; + +const StyledText = styled(H3)` + text-align: center; +`; + +const StyledErrorText = styled(Text)` + font-size: 20px; + padding-top: 1rem; + color: red; +`; diff --git a/apps/sso/middleware.ts b/apps/sso/middleware.ts index 30f567ba..9b7cc3d0 100644 --- a/apps/sso/middleware.ts +++ b/apps/sso/middleware.ts @@ -5,7 +5,7 @@ const REGISTERED_PATHS = new Set([ 'login', 'reset', 'reset-email', - 'reset-redirect', + 'reset-verify', 'signup', 'verify', 'logout', diff --git a/apps/sso/pages/reset-redirect/index.tsx b/apps/sso/pages/reset-redirect/index.tsx deleted file mode 100644 index 6979a542..00000000 --- a/apps/sso/pages/reset-redirect/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import styled from 'styled-components'; -import Head from 'next/head'; -import { getWebTitle } from '@hibiscus/metadata'; -import { useRouter } from 'next/router'; -import { useMemo } from 'react'; -import { Button } from '@hibiscus/ui-kit-2023'; - -export function Index() { - const router = useRouter(); - - // Extract redirect url from the query params - // This is required due to https://github.com/supabase/gotrue/issues/713 - const redirect = useMemo(() => router?.query?.url?.toString(), [router]); - - return ( - - - {getWebTitle('Reset your password')} - - - - {redirect && ( - - - - )} - - - ); -} -export default Index; - -const MainPageWrapper = styled.div` - display: flex; - flex-direction: column; - justify-content: space-between; - min-height: 100vh; -`; - -const CenterDiv = styled.div` - margin: auto; -`; diff --git a/apps/sso/pages/reset-verify/index.tsx b/apps/sso/pages/reset-verify/index.tsx new file mode 100644 index 00000000..df3ad13f --- /dev/null +++ b/apps/sso/pages/reset-verify/index.tsx @@ -0,0 +1,24 @@ +import styled from 'styled-components'; +import Head from 'next/head'; +import { getWebTitle } from '@hibiscus/metadata'; +import ResetVerifyCard from '../../components/verify-card/reset-verify-card'; + +export function Index() { + return ( + + + {getWebTitle('Reset your password')} + + + + + ); +} +export default Index; + +const MainPageWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 100vh; +`;