From e261e1df281cbae02493136d69f3a29b8354bcef Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:44:07 +0900 Subject: [PATCH 01/17] =?UTF-8?q?design:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/images/googleIcon.svg | 6 ++++++ public/images/loginLogo.svg | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 public/images/googleIcon.svg create mode 100644 public/images/loginLogo.svg diff --git a/public/images/googleIcon.svg b/public/images/googleIcon.svg new file mode 100644 index 0000000..2b5c694 --- /dev/null +++ b/public/images/googleIcon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/loginLogo.svg b/public/images/loginLogo.svg new file mode 100644 index 0000000..a9c6108 --- /dev/null +++ b/public/images/loginLogo.svg @@ -0,0 +1,8 @@ + + + + + + + + From 279ad7bec874e22989405414d178e12eed91bed9 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:44:37 +0900 Subject: [PATCH 02/17] =?UTF-8?q?build:=20=EA=B5=AC=EA=B8=80=20=EC=96=B4?= =?UTF-8?q?=EC=8A=A4=20=EB=B9=8C=EB=93=9C=20=ED=8C=8C=EC=9D=BC=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 10 ++++++++++ package.json | 1 + 2 files changed, 11 insertions(+) diff --git a/package-lock.json b/package-lock.json index acdcd26..2f530e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@craco/craco": "^7.1.0", "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", + "@react-oauth/google": "^0.12.1", "@tanstack/react-query": "^5.51.15", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", @@ -4722,6 +4723,15 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-oauth/google": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.12.1.tgz", + "integrity": "sha512-qagsy22t+7UdkYAiT5ZhfM4StXi9PPNvw0zuwNmabrWyMKddczMtBIOARflbaIj+wHiQjnMAsZmzsUYuXeyoSg==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@remix-run/router": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", diff --git a/package.json b/package.json index 1340bb1..e56a17d 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@craco/craco": "^7.1.0", "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", + "@react-oauth/google": "^0.12.1", "@tanstack/react-query": "^5.51.15", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", From 653620d0d4720f9405eca1d63b985e073d2e6c82 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:45:01 +0900 Subject: [PATCH 03/17] =?UTF-8?q?feat:=20path=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/path.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/routes/path.ts b/src/routes/path.ts index 342c8b7..3561932 100644 --- a/src/routes/path.ts +++ b/src/routes/path.ts @@ -1,8 +1,11 @@ export const RouterPath = { - root: "/", - home: "/", - mail: "/mail", - terms: "/terms", - privacy: "/privacy", - contact: "/contact", -} + root: '/', + home: '/', + mail: '/mail', + terms: '/terms', + privacy: '/privacy', + contact: '/contact', + login: '/login', + mypage: '/mypage', + notFound: '*', +}; From 479b466e2a39e58184b8c1f7522714c22caabd93 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:45:40 +0900 Subject: [PATCH 04/17] =?UTF-8?q?feat=20:=20=EB=A6=AC=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=A0=89=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/components/PrivateRoute.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/routes/components/PrivateRoute.tsx diff --git a/src/routes/components/PrivateRoute.tsx b/src/routes/components/PrivateRoute.tsx new file mode 100644 index 0000000..b62aa8f --- /dev/null +++ b/src/routes/components/PrivateRoute.tsx @@ -0,0 +1,13 @@ +import { useAuth } from '@/Provider/Auth'; +import { RouterPath } from '../path'; +import { Navigate, Outlet } from 'react-router-dom'; + +export const PrivateRoute = () => { + const { authInfo } = useAuth(); + + if (authInfo) { + return ; + } + + return ; +}; From cf958992cee0cabd8da56436e9e35c149de15092 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:46:04 +0900 Subject: [PATCH 05/17] =?UTF-8?q?feat:=20auth=20provider=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Provider/Auth.tsx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/Provider/Auth.tsx diff --git a/src/Provider/Auth.tsx b/src/Provider/Auth.tsx new file mode 100644 index 0000000..633a238 --- /dev/null +++ b/src/Provider/Auth.tsx @@ -0,0 +1,26 @@ +import { AuthContextType, AuthInfo } from '@/types'; +import { createContext, useContext, useState, ReactNode } from 'react'; + +export const AuthContext = createContext(undefined); + +export const AuthProvider = ({ children }: { children: ReactNode }) => { + const [authInfo, setAuthInfo] = useState(undefined); + + const updateAuthInfo = (auth: AuthInfo) => { + if (auth) { + setAuthInfo(auth); + } + }; + + return ( + {children} + ); +}; + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) { + throw new Error('useAuth must be used within an AuthProvider'); + } + return context; +}; From 4c61e4f93e9062365e73937e2b9ef980ee76b0b9 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:46:29 +0900 Subject: [PATCH 06/17] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20typ?= =?UTF-8?q?e=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types/index.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/types/index.ts b/src/types/index.ts index a128e26..8ae841d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -31,3 +31,17 @@ export interface Question { } export type MailInput = mailSendUniv | mailSendBusiness; + +export interface LoginResponse { + accessToken: String; + name: String; + picture: String; + email: String; +} + +export type AuthInfo = LoginResponse; + +export interface AuthContextType { + authInfo?: AuthInfo; + updateAuthInfo: (auth: AuthInfo) => void; +} From 3f3506371a802ce26e26475a6652469b28135406 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:47:32 +0900 Subject: [PATCH 07/17] =?UTF-8?q?refactor:=20header=20=ED=8F=B4=EB=8D=94?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=ED=9B=84=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Layout/Header/HeaderWithout.tsx | 136 ++++++++++++++++ src/components/Layout/Header/MainHeader.tsx | 150 ++++++++++++++++++ 2 files changed, 286 insertions(+) create mode 100644 src/components/Layout/Header/HeaderWithout.tsx create mode 100644 src/components/Layout/Header/MainHeader.tsx diff --git a/src/components/Layout/Header/HeaderWithout.tsx b/src/components/Layout/Header/HeaderWithout.tsx new file mode 100644 index 0000000..4eedfd2 --- /dev/null +++ b/src/components/Layout/Header/HeaderWithout.tsx @@ -0,0 +1,136 @@ +import styled from '@emotion/styled'; +import { Link } from 'react-router-dom'; +import { Button } from '@chakra-ui/react'; +import { breakpoints } from '@/styles/variants'; +import { useMail } from '@/Provider/MailContext'; +import { RouterPath } from '@/routes/path'; +import { useAuth } from '@/Provider/Auth'; + +export const Header = () => { + const mailContext = useMail(); + + if (!mailContext) { + throw new Error('MailContext not found'); + } + const { handleMail } = mailContext; + + const handleMailInput = () => { + handleMail({ + sender: '', + content: '', + department: '', + studentId: '', + subject: '', + receiver: '', + }); + window.location.reload(); + }; + + const { authInfo } = useAuth(); + + return ( + + +
+ {authInfo ? ( + + My Page + + ) : ( + + Login + + )} +
+ + + + +
+ + AI 메일 생성하기 + +
+
+
+ ); +}; + +export const HEADER_HEIGHT = '80px'; + +const Wrapper = styled.header` + z-index: 100; + height: ${HEADER_HEIGHT}; + padding: 16px 40px; + position: fixed; + top: 0; + left: 0; + right: 0; + width: 100%; + background: linear-gradient(90deg, #e6e9ff 0%, #e5f3ff 100%); + box-shadow: 0px 2px 18px 2px rgba(0, 0, 0, 0.1); +`; + +const Logo = styled.img` + height: 48px; + cursor: pointer; +`; + +const Container = styled.div` + display: flex; + flex-direction: row; + font-size: 14px; + justify-content: space-between; +`; + +const AiButton = styled(Button)` + position: relative; + display: flex; + height: 40px; + width: 136px; + padding: 10px 20px; + border-radius: 20px; + align-items: center; + justify-content: center; + gap: 10px; + background-color: transparent; + color: #000000; + font-family: 'Inter', sans-serif; + font-weight: 400; + font-size: 14px; + line-height: 19.6px; + letter-spacing: -2%; + background-clip: padding-box; + + &:hover { + background: linear-gradient(to right, #6ab9f2, #7a89f0); + color: white; + } + + &:before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 20px; + padding: 1px; + background: linear-gradient(to right, #6ab9f2, #7a89f0); + -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + } +`; + +const AuthWrapper = styled.div` + cursor: pointer; +`; + +const LogoLink = styled(Link)` + margin-left: 250px; + + @media (max-width: ${breakpoints.md}) { + margin-left: 100px; + } +`; diff --git a/src/components/Layout/Header/MainHeader.tsx b/src/components/Layout/Header/MainHeader.tsx new file mode 100644 index 0000000..5243bc9 --- /dev/null +++ b/src/components/Layout/Header/MainHeader.tsx @@ -0,0 +1,150 @@ +import styled from '@emotion/styled'; +import { Link } from 'react-router-dom'; +import { Button } from '@chakra-ui/react'; +import { breakpoints } from '@/styles/variants'; +import { useMail } from '@/Provider/MailContext'; +import { RouterPath } from '@/routes/path'; +import { useAuth } from '@/Provider/Auth'; + +const scrollToSection = (sectionId: string) => { + const element = document.getElementById(sectionId); + if (element) { + const elementPosition = element.getBoundingClientRect().top + window.scrollY - 80; + window.scrollTo({ top: elementPosition, behavior: 'smooth' }); + } +}; + +export const MainHeader = () => { + const mailContext = useMail(); + + if (!mailContext) { + throw new Error('MailContext not found'); + } + const { handleMail } = mailContext; + + const handleMailInput = () => { + handleMail({ + sender: '', + content: '', + department: '', + studentId: '', + subject: '', + receiver: '', + }); + }; + + const { authInfo } = useAuth(); + + return ( + + +
+ {authInfo ? ( + + My Page + + ) : ( + + Login + + )} +
+ + + + +
+
+ scrollToSection('section2')}> 서비스 체험 + scrollToSection('section3')}> 기능 살펴보기 +
+ + AI 메일 생성하기 + +
+
+
+ ); +}; + +export const HEADER_HEIGHT = '80px'; + +const Wrapper = styled.header` + z-index: 100; + height: ${HEADER_HEIGHT}; + padding: 16px 40px; + background: linear-gradient(90deg, #e6e9ff 0%, #e5f3ff 100%); + box-shadow: 0px 2px 18px 2px rgba(0, 0, 0, 0.1); +`; + +const Logo = styled.img` + height: 48px; + cursor: pointer; +`; + +const Container = styled.div` + display: flex; + flex-direction: row; + font-size: 14px; + justify-content: space-between; +`; + +const AiButton = styled(Button)` + position: relative; + display: flex; + height: 40px; + width: 136px; + padding: 10px 20px; + border-radius: 20px; + align-items: center; + justify-content: center; + gap: 10px; + background-color: transparent; + color: #000000; + font-family: 'Inter', sans-serif; + font-weight: 400; + font-size: 14px; + line-height: 19.6px; + letter-spacing: -2%; + background-clip: padding-box; + + &:hover { + background: linear-gradient(to right, #6ab9f2, #7a89f0); + color: white; + } + + &:before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 20px; + padding: 1px; + background: linear-gradient(to right, #6ab9f2, #7a89f0); + -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + } +`; + +const MidWrapper = styled.div` + cursor: pointer; + margin: 0px 20px; + @media (max-width: ${breakpoints.md}) { + display: none; + } +`; + +const LogoLink = styled(Link)` + margin-left: 250px; + + @media (max-width: ${breakpoints.md}) { + margin-left: 100px; + } +`; + +const AuthWrapper = styled.div` + cursor: pointer; +`; From 57852a1734c73c099542097b3c97381dce14d623 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:47:58 +0900 Subject: [PATCH 08/17] =?UTF-8?q?feat:=20auth=20provider=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index e436dd4..5e26f7f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,13 +4,16 @@ import { ChakraProvider } from '@chakra-ui/react'; import { theme } from '@/styles/variants/index'; import { QueryClientProvider } from '@tanstack/react-query'; import { queryClient } from './api'; +import { AuthProvider } from './Provider/Auth'; const App = () => { return ( - + + + From 050a5b94eab32808cdc84d0fb9991e6cc884dc44 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:49:36 +0900 Subject: [PATCH 09/17] =?UTF-8?q?design:=20=EC=B2=B4=ED=97=98=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EB=B0=8F=20=EB=A9=94=EC=9D=BC=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HomePage/TestersBox/Header.tsx | 17 +++++++++++++++++ src/components/Mail/Header.tsx | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/HomePage/TestersBox/Header.tsx b/src/components/HomePage/TestersBox/Header.tsx index 25cf29e..0e38290 100644 --- a/src/components/HomePage/TestersBox/Header.tsx +++ b/src/components/HomePage/TestersBox/Header.tsx @@ -1,3 +1,4 @@ +import { breakpoints } from '@/styles/variants'; import styled from '@emotion/styled'; interface HeaderProps { @@ -44,6 +45,12 @@ const Student = styled.div` position: relative; z-index: 2; bottom: -13px; + + @media (max-width: ${breakpoints.md}) { + bottom: 11px; + left: 120px; + box-shadow: ${(props) => (props.isActive === 'univ' ? '4px #6AB9F2' : 'none')}; + } `; const Business = styled.div` @@ -53,6 +60,12 @@ const Business = styled.div` position: relative; z-index: 2; bottom: -13px; + + @media (max-width: ${breakpoints.md}) { + bottom: 11px; + left: 120px; + box-shadow: ${(props) => (props.isActive === 'business' ? '4px #6AB9F2' : 'none')}; + } `; const Bar = styled.div` @@ -61,4 +74,8 @@ const Bar = styled.div` height: 3px; position: absolute; bottom: 8px; + + @media (max-width: ${breakpoints.md}) { + visibility: hidden; + } `; diff --git a/src/components/Mail/Header.tsx b/src/components/Mail/Header.tsx index 36482a3..215c691 100644 --- a/src/components/Mail/Header.tsx +++ b/src/components/Mail/Header.tsx @@ -79,6 +79,6 @@ const Bar = styled.div` position: absolute; bottom: 8px; @media (max-width: ${breakpoints.md}) { - width: 400px; + visibility: hidden; } `; From f20e02554fb0df98f0253773543e7630e13d668d Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:49:57 +0900 Subject: [PATCH 10/17] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Login/AuthCallback.tsx | 46 ++++++++++++++++++++++++++++++++ src/pages/Login/index.tsx | 41 ++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/pages/Login/AuthCallback.tsx create mode 100644 src/pages/Login/index.tsx diff --git a/src/pages/Login/AuthCallback.tsx b/src/pages/Login/AuthCallback.tsx new file mode 100644 index 0000000..5aa85da --- /dev/null +++ b/src/pages/Login/AuthCallback.tsx @@ -0,0 +1,46 @@ +import React, { useEffect, useState } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { useGetLogin } from '@/api/hooks/useGetLogin'; + +const AuthCallback = () => { + const { search } = useLocation(); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); + const [code, setCode] = useState(''); + const navigate = useNavigate(); + + const { data } = useGetLogin({ code }); + + useEffect(() => { + const queryParams = new URLSearchParams(search); + const token = queryParams.get('access_token'); + + if (token) { + // 액세스 토큰을 상태에 저장하고 후속 작업 수행 + setCode(token); + + // 예를 들어, 사용자를 메인 페이지로 리디렉션 + navigate('/home'); + } else { + setError('Failed to retrieve access token'); + } + setLoading(false); + }, [search, navigate]); + + if (loading) { + return

Loading...

; // 로딩 화면 표시 + } + + if (error) { + return

{error}

; // 오류 메시지 표시 + } + + return ( +
+

Authentication Successful

+

Access Token: {code}

{/* 액세스 토큰을 표시하거나 다른 작업 수행 */} +
+ ); +}; + +export default AuthCallback; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx new file mode 100644 index 0000000..02652ed --- /dev/null +++ b/src/pages/Login/index.tsx @@ -0,0 +1,41 @@ +import styled from '@emotion/styled'; + +export const Login = () => { + return ( + + 로그인 이미지 + + + 구글 아이콘구글 계정으로 로그인 + + + + ); +}; + +const Wrapper = styled.div` + width: 630px; + height: 670px; +`; + +const LoginButton = styled.button` + display: flex; + width: 473px; + height: 50px; + padding: 0px 19px; + justify-content: center; + align-items: center; + gap: 6px; + flex-shrink: 0; + border-radius: 5px; + background: var(--Grey900, #1c1c1e); + color: #fff; + + /* Title5/Inter/Bold/16pt/-2% */ + font-family: Inter; + font-size: 16px; + font-style: normal; + font-weight: 700; + line-height: 140%; /* 22.4px */ + letter-spacing: -0.32px; +`; From 17311b8ba5475d43ab3baec3fbf03d92ed8eae10 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:50:13 +0900 Subject: [PATCH 11/17] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/MyPage/index.tsx | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/pages/MyPage/index.tsx diff --git a/src/pages/MyPage/index.tsx b/src/pages/MyPage/index.tsx new file mode 100644 index 0000000..6c1f88a --- /dev/null +++ b/src/pages/MyPage/index.tsx @@ -0,0 +1,3 @@ +export const MyPage = () => { + return
마이 페이지
; +}; From 8a7b3380fbdb23f4685e9d0dd6b15baba03717f4 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:50:39 +0900 Subject: [PATCH 12/17] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=9B=85=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/hooks/useGetLogin.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/api/hooks/useGetLogin.tsx diff --git a/src/api/hooks/useGetLogin.tsx b/src/api/hooks/useGetLogin.tsx new file mode 100644 index 0000000..749b643 --- /dev/null +++ b/src/api/hooks/useGetLogin.tsx @@ -0,0 +1,22 @@ +import { useQuery } from '@tanstack/react-query'; +import { LoginResponse } from '@/types'; +import { BASE_URL } from '..'; +import axios from 'axios'; + +export type AuthResponse = { + code: string; +}; + +export const getLoginPath = (code: string) => `${BASE_URL}/google/login/redirect?code=${code}`; + +export const getLogin = async ({ code }: AuthResponse): Promise => { + const response = await axios.get(getLoginPath(code)); + return response.data; +}; + +export const useGetLogin = (params: AuthResponse) => { + return useQuery({ + queryKey: ['getLogin', params.code], + queryFn: () => getLogin(params), + }); +}; From a9dda7dd4cfa5edd7c214d76c25203cb551c2116 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:51:13 +0900 Subject: [PATCH 13/17] =?UTF-8?q?design:=20mail=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Mail/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Mail/index.tsx b/src/pages/Mail/index.tsx index 55ff4c6..ba7b05a 100644 --- a/src/pages/Mail/index.tsx +++ b/src/pages/Mail/index.tsx @@ -45,6 +45,7 @@ export const MailPage = () => { h="100%" templateRows={{ base: 'auto auto auto', md: '106px 780px' }} templateColumns={{ base: 'repeat(1, 1fr)', md: 'repeat(1, 1fr)' }} + gap={2} > { onClose={closeModal} /> - Date: Wed, 7 Aug 2024 15:51:51 +0900 Subject: [PATCH 14/17] =?UTF-8?q?design:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HomePage/Contents.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/HomePage/Contents.tsx b/src/components/HomePage/Contents.tsx index ff2a2a1..9c83eec 100644 --- a/src/components/HomePage/Contents.tsx +++ b/src/components/HomePage/Contents.tsx @@ -1,21 +1,24 @@ import { Grid, GridItem } from '@chakra-ui/react'; import { ContentsInfo } from '@/components/HomePage/ContentsInfo'; import { TestersBox } from './TestersBox'; -import { TopContents } from './TopContents'; export const Contents = () => { return ( - - - - + From 262ccd0550962e279045a12504078624a4b970e0 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:52:18 +0900 Subject: [PATCH 15/17] =?UTF-8?q?design:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=B2=B4=ED=97=98=ED=95=98=EA=B8=B0=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HomePage/TestersBox/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/HomePage/TestersBox/index.tsx b/src/components/HomePage/TestersBox/index.tsx index 3a2beff..f6ea5d1 100644 --- a/src/components/HomePage/TestersBox/index.tsx +++ b/src/components/HomePage/TestersBox/index.tsx @@ -52,6 +52,7 @@ export const TestersBox = () => { h="100%" templateRows={{ base: 'auto 1fr', md: '106px 780px' }} templateColumns={{ base: 'repeat(1, 1fr)', md: 'repeat(1, 1fr)' }} + gap={5} > Date: Wed, 7 Aug 2024 15:52:55 +0900 Subject: [PATCH 16/17] =?UTF-8?q?feat:=20routes=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/index.tsx | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/routes/index.tsx b/src/routes/index.tsx index f735b18..ff55c11 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -4,15 +4,25 @@ import { MailPage } from '@/pages/Mail'; import { Layout } from '@/components/Layout'; import { NoFooterLayout } from '@/components/Layout/noFooterIndex'; import { RouterPath } from './path'; -import {Terms} from '@/pages/Extra/Terms'; -import {Privacy} from '@/pages/Extra/Privacy'; -import {Contact} from '@/pages/Extra/Contact'; +import { Terms } from '@/pages/Extra/Terms'; +import { Privacy } from '@/pages/Extra/Privacy'; +import { Contact } from '@/pages/Extra/Contact'; +import { Login } from '@/pages/Login'; +import { MyPage } from '@/pages/MyPage'; +import { PrivateRoute } from './components/PrivateRoute'; +import { Navigate } from 'react-router-dom'; const router = createBrowserRouter([ { path: RouterPath.root, element: , - children: [{ path: RouterPath.home, element: }], + children: [ + { path: RouterPath.home, element: }, + { + path: RouterPath.notFound, + element: , + }, + ], }, { path: RouterPath.root, @@ -22,8 +32,17 @@ const router = createBrowserRouter([ { path: RouterPath.terms, element: }, { path: RouterPath.privacy, element: }, { path: RouterPath.contact, element: }, + { + path: RouterPath.mypage, + element: , + children: [{ path: RouterPath.mypage, element: }], + }, ], }, + { + path: RouterPath.login, + element: , + }, ]); export const Routes = () => { From 8732f9c1d3017139ca795edbddf21990b06a75e0 Mon Sep 17 00:00:00 2001 From: seung365 Date: Wed, 7 Aug 2024 15:53:11 +0900 Subject: [PATCH 17/17] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B0=8F=20=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HomePage/TopContents.tsx | 18 ---- src/components/Layout/Header.tsx | 137 ------------------------ src/components/Layout/MainHeader.tsx | 131 ---------------------- src/components/Layout/index.tsx | 2 +- src/components/Layout/noFooterIndex.tsx | 2 +- 5 files changed, 2 insertions(+), 288 deletions(-) delete mode 100644 src/components/HomePage/TopContents.tsx delete mode 100644 src/components/Layout/Header.tsx delete mode 100644 src/components/Layout/MainHeader.tsx diff --git a/src/components/HomePage/TopContents.tsx b/src/components/HomePage/TopContents.tsx deleted file mode 100644 index 9daa9c5..0000000 --- a/src/components/HomePage/TopContents.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import styled from '@emotion/styled'; -import { Image } from '@chakra-ui/react'; - -export const TopContents = () => { - return ( - - - - ); -}; - -const Wrapper = styled.div` - width: 100%; - height: 600px; - display: flex; - align-items: center; - justify-content: center; -`; diff --git a/src/components/Layout/Header.tsx b/src/components/Layout/Header.tsx deleted file mode 100644 index 136fbf7..0000000 --- a/src/components/Layout/Header.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import styled from '@emotion/styled'; -import { Link } from 'react-router-dom'; -import { Button } from '@chakra-ui/react'; -import { breakpoints } from '@/styles/variants'; -import { useMail } from '@/Provider/MailContext'; - -const scrollToSection = (sectionId: string) => { - const element = document.getElementById(sectionId); - if (element) { - const elementPosition = element.getBoundingClientRect().top + window.scrollY - 80; - window.scrollTo({ top: elementPosition, behavior: 'smooth' }); - } -}; - -export const Header = () => { - const mailContext = useMail(); - - if (!mailContext) { - throw new Error('MailContext not found'); - } - const { handleMail } = mailContext; - - const handleMailInput = () => { - handleMail({ - sender: '', - content: '', - department: '', - studentId: '', - subject: '', - receiver: '', - }); - window.location.reload(); - }; - - return ( - - -
Login
- - - -
-
- scrollToSection('section2')}> 서비스 체험 - scrollToSection('section3')}> 기능 살펴보기 -
- - AI 메일 생성하기 - -
-
-
- ); -}; - -export const HEADER_HEIGHT = '80px'; - -const Wrapper = styled.header` - z-index: 100; - height: ${HEADER_HEIGHT}; - padding: 16px 40px; - position: fixed; - top: 0; - left: 0; - right: 0; - width: 100%; - background: linear-gradient(90deg, #e6e9ff 0%, #e5f3ff 100%); - box-shadow: 0px 2px 18px 2px rgba(0, 0, 0, 0.1); -`; - -const Logo = styled.img` - height: 48px; - cursor: pointer; -`; - -const Container = styled.div` - display: flex; - flex-direction: row; - font-size: 14px; - justify-content: space-between; -`; - -const AiButton = styled(Button)` - position: relative; - display: flex; - height: 40px; - width: 136px; - padding: 10px 20px; - border-radius: 20px; - align-items: center; - justify-content: center; - gap: 10px; - background-color: transparent; - color: #000000; - font-family: 'Inter', sans-serif; - font-weight: 400; - font-size: 14px; - line-height: 19.6px; - letter-spacing: -2%; - background-clip: padding-box; - - &:hover { - background: linear-gradient(to right, #6ab9f2, #7a89f0); - color: white; - } - - &:before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border-radius: 20px; - padding: 1px; - background: linear-gradient(to right, #6ab9f2, #7a89f0); - -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); - -webkit-mask-composite: xor; - mask-composite: exclude; - } -`; - -const MidWrapper = styled.div` - cursor: pointer; - margin: 0px 20px; - @media (max-width: ${breakpoints.md}) { - display: none; - } -`; - -const LogoLink = styled(Link)` - margin-left: 250px; - - @media (max-width: ${breakpoints.md}) { - margin-left: 100px; - } -`; diff --git a/src/components/Layout/MainHeader.tsx b/src/components/Layout/MainHeader.tsx deleted file mode 100644 index fe0ec50..0000000 --- a/src/components/Layout/MainHeader.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import styled from '@emotion/styled'; -import { Link } from 'react-router-dom'; -import { Button } from '@chakra-ui/react'; -import { breakpoints } from '@/styles/variants'; -import { useMail } from '@/Provider/MailContext'; - -const scrollToSection = (sectionId: string) => { - const element = document.getElementById(sectionId); - if (element) { - const elementPosition = element.getBoundingClientRect().top + window.scrollY - 80; - window.scrollTo({ top: elementPosition, behavior: 'smooth' }); - } -}; - -export const MainHeader = () => { - const mailContext = useMail(); - - if (!mailContext) { - throw new Error('MailContext not found'); - } - const { handleMail } = mailContext; - - const handleMailInput = () => { - handleMail({ - sender: '', - content: '', - department: '', - studentId: '', - subject: '', - receiver: '', - }); - }; - - return ( - - -
Login
- - - -
-
- scrollToSection('section2')}> 서비스 체험 - scrollToSection('section3')}> 기능 살펴보기 -
- - AI 메일 생성하기 - -
-
-
- ); -}; - -export const HEADER_HEIGHT = '80px'; - -const Wrapper = styled.header` - z-index: 100; - height: ${HEADER_HEIGHT}; - padding: 16px 40px; - background: linear-gradient(90deg, #e6e9ff 0%, #e5f3ff 100%); - box-shadow: 0px 2px 18px 2px rgba(0, 0, 0, 0.1); -`; - -const Logo = styled.img` - height: 48px; - cursor: pointer; -`; - -const Container = styled.div` - display: flex; - flex-direction: row; - font-size: 14px; - justify-content: space-between; -`; - -const AiButton = styled(Button)` - position: relative; - display: flex; - height: 40px; - width: 136px; - padding: 10px 20px; - border-radius: 20px; - align-items: center; - justify-content: center; - gap: 10px; - background-color: transparent; - color: #000000; - font-family: 'Inter', sans-serif; - font-weight: 400; - font-size: 14px; - line-height: 19.6px; - letter-spacing: -2%; - background-clip: padding-box; - - &:hover { - background: linear-gradient(to right, #6ab9f2, #7a89f0); - color: white; - } - - &:before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border-radius: 20px; - padding: 1px; - background: linear-gradient(to right, #6ab9f2, #7a89f0); - -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); - -webkit-mask-composite: xor; - mask-composite: exclude; - } -`; - -const MidWrapper = styled.div` - cursor: pointer; - margin: 0px 20px; - @media (max-width: ${breakpoints.md}) { - display: none; - } -`; - -const LogoLink = styled(Link)` - margin-left: 250px; - - @media (max-width: ${breakpoints.md}) { - margin-left: 100px; - } -`; diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 528b2fd..472220a 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { Outlet } from 'react-router-dom'; import { Footer } from './Footer'; -import { HEADER_HEIGHT, MainHeader } from './MainHeader'; +import { HEADER_HEIGHT, MainHeader } from './Header/MainHeader'; import { UpperImage } from './UpperImage'; export const Layout = () => { diff --git a/src/components/Layout/noFooterIndex.tsx b/src/components/Layout/noFooterIndex.tsx index 5803991..a574317 100644 --- a/src/components/Layout/noFooterIndex.tsx +++ b/src/components/Layout/noFooterIndex.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; import { Outlet } from 'react-router-dom'; -import { Header, HEADER_HEIGHT } from './Header'; +import { Header, HEADER_HEIGHT } from './Header/HeaderWithout'; export const NoFooterLayout = () => { return (