diff --git a/src/@types/styles/size.ts b/src/@types/styles/size.ts index 10b73b69..666f693c 100644 --- a/src/@types/styles/size.ts +++ b/src/@types/styles/size.ts @@ -1,6 +1,12 @@ import { CSSProperties } from 'react'; -export type SizeOption = 'large' | 'medium' | 'small' | 'tiny' | 'building'; +export type SizeOption = + | 'large' + | 'medium' + | 'small' + | 'tiny' + | 'halfCard' + | 'building'; export interface Size { height: CSSProperties['height']; diff --git a/src/components/BodyLayout/index.tsx b/src/components/BodyLayout/index.tsx index dc97d7ed..f9241247 100644 --- a/src/components/BodyLayout/index.tsx +++ b/src/components/BodyLayout/index.tsx @@ -1,4 +1,5 @@ import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; import React from 'react'; import { Outlet } from 'react-router-dom'; @@ -13,6 +14,7 @@ const BodyLayout = () => { export default BodyLayout; const StyledBodyLayout = styled.div` + background-color: ${THEME.BACKGROUND}; height: calc(100vh - 8vh - 90px); padding: 8vh 0 8vh 0; overflow-y: scroll; diff --git a/src/components/Card/InformCard/index.tsx b/src/components/Card/InformCard/index.tsx index 67b95b32..0671724b 100644 --- a/src/components/Card/InformCard/index.tsx +++ b/src/components/Card/InformCard/index.tsx @@ -50,10 +50,7 @@ const InformCard = ({ - - {title} - {title} 보러가기 - + {title} ); }; @@ -61,31 +58,13 @@ const InformCard = ({ export default InformCard; const Card = styled.div` - padding: 3% 1% 2% 0; + padding: 5% 0 0 0; height: 4rem; display: flex; align-items: center; - - span:nth-of-type(1) { - font-size: 12px; - color: ${THEME.TEXT.GRAY}; - } - - span:nth-of-type(2) { - font-size: 16px; - font-weight: bold; - color: ${THEME.TEXT.BLACK}; - } - transition: all 0.2s ease-in-out; `; -const TextContainer = styled.div` - display: flex; - flex-direction: column; - gap: 5px; -`; - const IconContainer = styled.div` height: 45px; width: 45px; @@ -96,3 +75,8 @@ const IconContainer = styled.div` border-radius: 50%; background-color: ${THEME.PRIMARY}; `; + +const InfoTitle = styled.span` + font-size: 1rem; + font-weight: bold; +`; diff --git a/src/pages/Home/components/InformHalfCard.tsx b/src/components/Card/InformHalfCard/index.tsx similarity index 59% rename from src/pages/Home/components/InformHalfCard.tsx rename to src/components/Card/InformHalfCard/index.tsx index 76b59243..a58bf900 100644 --- a/src/pages/Home/components/InformHalfCard.tsx +++ b/src/components/Card/InformHalfCard/index.tsx @@ -1,27 +1,21 @@ -import Icon from '@components/Common/Icon'; import styled from '@emotion/styled'; -import useRouter from '@hooks/useRouter'; import { THEME } from '@styles/ThemeProvider/theme'; -import { IconKind } from '@type/styles/icon'; -interface InformHalfCardProps { - iconKind: IconKind; +interface InformHalfCardProps extends React.HTMLAttributes { + asset: () => JSX.Element; title: string; subTitle: string; - link: string; } const InformHalfCard = ({ - iconKind, + asset, title, subTitle, - link, + ...props }: InformHalfCardProps) => { - const { routerTo } = useRouter(); - return ( - routerTo(link)}> - + + {asset()} {subTitle} {title} @@ -33,32 +27,32 @@ const InformHalfCard = ({ export default InformHalfCard; const Container = styled.div` + padding: 3% 5% 3% 5%; + width: 90%; + height: 55px; display: flex; align-items: center; justify-content: space-between; - width: 39%; - background-color: ${THEME.IVORY}; - padding: 3% 5% 3% 4%; + background-color: ${THEME.BACKGROUND}; border-radius: 15px; - box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; - height: 55px; + box-shadow: rgba(0, 0, 0, 0.3) 0px 3px 8px; `; const TitleWrapper = styled.div` display: flex; flex-direction: column; - padding-left: 7px; + align-items: flex-end; `; const Title = styled.h2` - font-size: 16px; font-weight: bold; + font-size: 12px; `; const SubTitle = styled.h3` color: ${THEME.TEXT.SEMIBLACK}; display: flex; justify-content: flex-end; - font-size: 13px; padding-bottom: 6px; + font-size: 10px; `; diff --git a/src/components/Card/TipCard/TipImage.tsx b/src/components/Card/TipCard/TipImage.tsx index 10db07ed..ba09162c 100644 --- a/src/components/Card/TipCard/TipImage.tsx +++ b/src/components/Card/TipCard/TipImage.tsx @@ -1,31 +1,29 @@ -import Image from '@components/Common/Image'; +import WebpImage from '@components/Common/WebpImage'; import { css } from '@emotion/react'; import React from 'react'; interface TipImageProps { title: string; webpPath: string; - pngPath: string; + normalPath: string; } -const TipImage = ({ title, webpPath, pngPath }: TipImageProps) => { +const TipImage = ({ title, webpPath, normalPath }: TipImageProps) => { return ( - - - {title} - + ); }; diff --git a/src/components/Common/Button/index.tsx b/src/components/Common/Button/index.tsx index fda2471d..029336c8 100644 --- a/src/components/Common/Button/index.tsx +++ b/src/components/Common/Button/index.tsx @@ -19,22 +19,18 @@ const Button = ({ children, disabled = false, ...props }: ButtonProps) => { export default Button; const StyledButton = styled.button` + height: 50px; + width: 100%; + padding: 10px; + margin: 4px 0; display: flex; justify-content: center; align-items: center; - - cursor: pointer; - - width: 100%; - height: 50px; - margin: 4px 0; - - border-radius: 8px; - padding: 10px; - background-color: ${THEME.BUTTON.BLUE}; color: #ffffff; font-weight: bold; + border-radius: 8px; + cursor: pointer; &:disabled { background-color: ${THEME.BUTTON.GRAY}; diff --git a/src/components/Common/Image/index.tsx b/src/components/Common/Image/index.tsx index b9a24ee7..4bcbdddc 100644 --- a/src/components/Common/Image/index.tsx +++ b/src/components/Common/Image/index.tsx @@ -8,6 +8,7 @@ const imageSize: ImageSize = { medium: setSize(150), small: setSize(100), tiny: setSize(80), + halfCard: setSize(50, 60), building: setSize(100, 180), }; diff --git a/src/components/Common/WebpImage/index.tsx b/src/components/Common/WebpImage/index.tsx new file mode 100644 index 00000000..0b04a02c --- /dev/null +++ b/src/components/Common/WebpImage/index.tsx @@ -0,0 +1,28 @@ +import { SizeOption } from '@type/styles/size'; +import React from 'react'; + +import Image from '../Image'; + +interface WebpImageProps extends React.ImgHTMLAttributes { + wepbPath: string; + normalPath: string; + title: string; + size?: SizeOption; +} + +const WebpImage = ({ + wepbPath, + normalPath, + title, + size = 'medium', + ...props +}: WebpImageProps) => { + return ( + + + {title} + + ); +}; + +export default WebpImage; diff --git a/src/components/InformUpperLayout/InformSearchForm.tsx b/src/components/InformUpperLayout/InformSearchForm.tsx index 4f71707b..1964d17a 100644 --- a/src/components/InformUpperLayout/InformSearchForm.tsx +++ b/src/components/InformUpperLayout/InformSearchForm.tsx @@ -5,6 +5,7 @@ import TOAST_MESSAGES from '@constants/toast-message'; import styled from '@emotion/styled'; import useRouter from '@hooks/useRouter'; import useToasts from '@hooks/useToast'; +import { THEME } from '@styles/ThemeProvider/theme'; import React, { useRef } from 'react'; interface InformSearchForm { @@ -60,12 +61,12 @@ const StyledInput = styled.input` border: 0; border-radius: 15px; background-color: #7a9dd30f; - color: #7a9dd366; + color: ${THEME.TEXT.BLACK}; font-size: 14px; text-indent: 5px; &::placeholder { - color: #7a9dd366; + color: ${THEME.TEXT.GRAY}; font-size: 14px; } box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.15); diff --git a/src/constants/announcement.ts b/src/constants/announcement.ts index 7559ee43..64c16f34 100644 --- a/src/constants/announcement.ts +++ b/src/constants/announcement.ts @@ -3,6 +3,12 @@ export const ANNOUNCEMENT_TITLE = { MAROR: '학과 공지사항', LANGUAGE: '어학 공지사항', RECRUIT: '채용 공지사항', + GRADUATION: '졸업요건', +}; + +export const ANNOUNCE_SUB_TITLE = { + RECURIT: '채용 정보 확인', + LANGUAGE: '어학 정보 확인', }; export const ANNOUNCEMENT_CATEGORY = { diff --git a/src/constants/tip.ts b/src/constants/tip.ts index 190518ec..89a25428 100644 --- a/src/constants/tip.ts +++ b/src/constants/tip.ts @@ -89,6 +89,13 @@ export const HONEY_TIP_DATA: readonly TipData[] = [ }, ] as const; +export const TIP_ROUTING_CARD = { + WEBP_PATH: '/assets/tipImages/webp/baekgyeong_suprised.webp', + NORMAL_PATH: '/assets/tipImages/png/baekgyeong_suprised.png', + TITLE: '꿀팁 사이트 바로가기', + SUB_TITLE: '부경대 꿀팁 사이트 모음', +}; + export const TIP_TYPE = { SHORTCUT: 'shortcut', HONEY_TIP: 'honeytip', diff --git a/src/pages/Home/Home.test.tsx b/src/pages/Home/Home.test.tsx index 54523aba..3e376e8d 100644 --- a/src/pages/Home/Home.test.tsx +++ b/src/pages/Home/Home.test.tsx @@ -6,6 +6,10 @@ import '@testing-library/jest-dom'; import Home from './index'; +interface TextInScreen { + [key: string]: string; +} + describe('Home Page 컴포넌트 테스트', () => { it('페이지에 공지사항 및 졸업요건 컴포넌트가 렌더링된다.', () => { render( @@ -18,10 +22,16 @@ describe('Home Page 컴포넌트 테스트', () => { wrapper: MemoryRouter, }, ); - const notificationText = screen.getByText('학교 공지사항'); - expect(notificationText).toBeInTheDocument(); - const requirementText = screen.getByText('졸업요건'); - expect(requirementText).toBeInTheDocument(); + const EXPECTED_TEXT: TextInScreen = { + school: '학교 공지사항 보러가기', + major: '학과 공지사항 보러가기', + graduation: '졸업요건 보러가기', + }; + + Object.keys(EXPECTED_TEXT).forEach((key) => { + const expectedText = screen.getByText(EXPECTED_TEXT[key]); + expect(expectedText).toBeInTheDocument(); + }); }); }); diff --git a/src/pages/Home/components/ExtraInfo.tsx b/src/pages/Home/components/ExtraInfo.tsx new file mode 100644 index 00000000..7169cfd0 --- /dev/null +++ b/src/pages/Home/components/ExtraInfo.tsx @@ -0,0 +1,68 @@ +import InformHalfCard from '@components/Card/InformHalfCard'; +import Icon from '@components/Common/Icon'; +import WebpImage from '@components/Common/WebpImage'; +import { + ANNOUNCEMENT_TITLE, + ANNOUNCE_SUB_TITLE, +} from '@constants/announcement'; +import PATH from '@constants/path'; +import { TIP_ROUTING_CARD } from '@constants/tip'; +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; +import useRouter from '@hooks/useRouter'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +const ExtraInfo = () => { + const { routerTo } = useRouter(); + + return ( + <> + + } + title={ANNOUNCEMENT_TITLE.RECRUIT} + subTitle={ANNOUNCE_SUB_TITLE.RECURIT} + onClick={() => routerTo(PATH.NORMAL_ANNOUNCEMENT('recruit'))} + /> + } + title={ANNOUNCEMENT_TITLE.LANGUAGE} + subTitle={ANNOUNCE_SUB_TITLE.LANGUAGE} + onClick={() => routerTo(PATH.NORMAL_ANNOUNCEMENT('language'))} + /> + + ( + + )} + title={TIP_ROUTING_CARD.TITLE} + subTitle={TIP_ROUTING_CARD.SUB_TITLE} + onClick={() => routerTo(PATH.TIP.SHORTCUT)} + css={css` + h2 { + font-size: 16px; + } + h3 { + font-size: 12px; + } + `} + /> + + ); +}; + +export default ExtraInfo; + +const FlatContainer = styled.div` + display: flex; + justify-content: space-around; + margin-top: 5%; + margin-bottom: 5%; + gap: 10px; +`; diff --git a/src/pages/Home/components/InformCardList.tsx b/src/pages/Home/components/SchoolInfo.tsx similarity index 51% rename from src/pages/Home/components/InformCardList.tsx rename to src/pages/Home/components/SchoolInfo.tsx index 603c7ecf..ecc0a2ed 100644 --- a/src/pages/Home/components/InformCardList.tsx +++ b/src/pages/Home/components/SchoolInfo.tsx @@ -2,13 +2,16 @@ import http from '@apis/http'; import InformCard from '@components/Card/InformCard'; import { ANNOUNCEMENT_TITLE } from '@constants/announcement'; import PATH from '@constants/path'; +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; import useMajor from '@hooks/useMajor'; import useRouter from '@hooks/useRouter'; +import { THEME } from '@styles/ThemeProvider/theme'; import openLink from '@utils/router/openLink'; import { AxiosResponse } from 'axios'; import React from 'react'; -const InformCardList = () => { +const SchoolInfo = () => { const { major } = useMajor(); const { routerTo } = useRouter(); @@ -17,31 +20,61 @@ const InformCardList = () => { `/api/graduation?major=${major}`, ); const graduationLink = response.data; + openLink(graduationLink); }; + const onTitleClick = () => { + if (major) return; + routerTo('/major-decision'); + }; + return ( - <> + + + {major ? major : '학과를 선택 해주세요'} + routerTo(PATH.NORMAL_ANNOUNCEMENT('school'))} /> routerTo(PATH.NORMAL_ANNOUNCEMENT('major'))} /> - + ); }; -export default InformCardList; +export default SchoolInfo; + +const Container = styled.div` + overflow: hidden; + border-radius: 15px; + padding: 5%; + background-color: ${THEME.BACKGROUND}; + margin-top: 5%; + box-shadow: rgba(0, 0, 0, 0.3) 0px 3px 8px; +`; + +const Title = styled.span<{ hasMajor: boolean }>` + font-size: 1rem; + font-weight: bold; + + ${({ hasMajor }) => + !hasMajor && + css` + color: ${THEME.TEXT.GRAY}; + border-bottom: 1px solid ${THEME.TEXT.GRAY}; + `} +`; diff --git a/src/pages/Home/components/Whalbe.tsx b/src/pages/Home/components/Whalbe.tsx new file mode 100644 index 00000000..1d73db41 --- /dev/null +++ b/src/pages/Home/components/Whalbe.tsx @@ -0,0 +1,29 @@ +import Carousel from '@components/Carousel'; +import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +const Whalbe = () => { + return ( + + 비교과 + + + ); +}; + +export default Whalbe; + +const Container = styled.div` + overflow: hidden; + border-radius: 15px; + padding: 5%; + background-color: ${THEME.BACKGROUND}; + margin-top: 5%; + box-shadow: rgba(0, 0, 0, 0.3) 0px 3px 8px; +`; + +const Title = styled.div` + font-size: 20px; + font-weight: bold; +`; diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index ac3e3ee7..3549752e 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,35 +1,15 @@ -import Carousel from '@components/Carousel'; import styled from '@emotion/styled'; -import InformHalfCard from '@pages/Home/components/InformHalfCard'; -import { THEME } from '@styles/ThemeProvider/theme'; -import InformCardList from './components/InformCardList'; +import ExtraInfo from './components/ExtraInfo'; +import SchoolInfo from './components/SchoolInfo'; +import Whalbe from './components/Whalbe'; const Home = () => { return ( - - 학교 - - - - - - - - 비교과 - - + + + ); }; @@ -39,27 +19,7 @@ export default Home; const Container = styled.div` display: flex; flex-direction: column; - width: 85%; + width: 90%; margin: 0 auto; - padding-bottom: 5%; -`; - -const InformCardWrapper = styled.div` - overflow: hidden; - border-radius: 15px; - padding: 5%; - background-color: ${THEME.IVORY}; - margin-top: 5%; - box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; -`; - -const InformHalfCardList = styled.div` - display: flex; - justify-content: space-between; - margin-top: 5%; -`; - -const InformTitle = styled.div` - font-size: 20px; - font-weight: bold; + padding-bottom: 15px; `; diff --git a/src/styles/ThemeProvider/theme.ts b/src/styles/ThemeProvider/theme.ts index 24226f17..fb13eb27 100644 --- a/src/styles/ThemeProvider/theme.ts +++ b/src/styles/ThemeProvider/theme.ts @@ -1,7 +1,7 @@ import { Theme } from '@emotion/react'; export const THEME: Theme = { - BACKGROUND: '#EAEAEA', + BACKGROUND: '#FFFFFF', TEXT: { BLACK: '#000000', @@ -18,5 +18,4 @@ export const THEME: Theme = { }, MODAL_BACKGROUND: 'rgba(0, 0, 0, 0.6)', - IVORY: '#fffef9', }; diff --git a/src/styles/emotion.d.ts b/src/styles/emotion.d.ts index faaddaeb..56ebb19d 100644 --- a/src/styles/emotion.d.ts +++ b/src/styles/emotion.d.ts @@ -18,6 +18,5 @@ declare module '@emotion/react' { }; MODAL_BACKGROUND: string; - IVORY: string; } }