diff --git a/public/assets/baekgyeong-speaker.png b/public/assets/baekgyeong-speaker.png deleted file mode 100644 index c8177981..00000000 Binary files a/public/assets/baekgyeong-speaker.png and /dev/null differ diff --git a/public/assets/baekgyeong-whalebe.png b/public/assets/baekgyeong-whalebe.png deleted file mode 100644 index d0a04d46..00000000 Binary files a/public/assets/baekgyeong-whalebe.png and /dev/null differ diff --git a/public/assets/pknu.png b/public/assets/pknu.png deleted file mode 100644 index 4b5a391a..00000000 Binary files a/public/assets/pknu.png and /dev/null differ diff --git a/public/assets/tipImages/png/baekgyeong_camera.png b/public/assets/tipImages/png/baekgyeong_camera.png new file mode 100644 index 00000000..7bf0a0d3 Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_camera.png differ diff --git a/public/assets/tipImages/png/baekgyeong_guide.png b/public/assets/tipImages/png/baekgyeong_guide.png new file mode 100644 index 00000000..954263d9 Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_guide.png differ diff --git a/public/assets/tipImages/png/baekgyeong_hi.png b/public/assets/tipImages/png/baekgyeong_hi.png new file mode 100644 index 00000000..3e414283 Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_hi.png differ diff --git a/public/assets/tipImages/png/baekgyeong_love.png b/public/assets/tipImages/png/baekgyeong_love.png new file mode 100644 index 00000000..2057fcf4 Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_love.png differ diff --git a/public/assets/tipImages/png/baekgyeong_search.png b/public/assets/tipImages/png/baekgyeong_search.png new file mode 100644 index 00000000..5ebe84e0 Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_search.png differ diff --git a/public/assets/tipImages/png/baekgyeong_suprised.png b/public/assets/tipImages/png/baekgyeong_suprised.png new file mode 100644 index 00000000..781114ef Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_suprised.png differ diff --git a/public/assets/tipImages/png/baekgyeong_teach.png b/public/assets/tipImages/png/baekgyeong_teach.png new file mode 100644 index 00000000..9a774224 Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_teach.png differ diff --git a/public/assets/tipImages/png/baekgyeong_underpin.png b/public/assets/tipImages/png/baekgyeong_underpin.png new file mode 100644 index 00000000..1ddc29fa Binary files /dev/null and b/public/assets/tipImages/png/baekgyeong_underpin.png differ diff --git a/public/assets/tipImages/png/pknu.png b/public/assets/tipImages/png/pknu.png new file mode 100644 index 00000000..126c52ac Binary files /dev/null and b/public/assets/tipImages/png/pknu.png differ diff --git a/public/assets/tipImages/webp/baekgyeong_camera.webp b/public/assets/tipImages/webp/baekgyeong_camera.webp new file mode 100644 index 00000000..0f347d75 Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_camera.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_guide.webp b/public/assets/tipImages/webp/baekgyeong_guide.webp new file mode 100644 index 00000000..3d1a92ae Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_guide.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_hi.webp b/public/assets/tipImages/webp/baekgyeong_hi.webp new file mode 100644 index 00000000..c3d32756 Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_hi.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_love.webp b/public/assets/tipImages/webp/baekgyeong_love.webp new file mode 100644 index 00000000..0ec1e410 Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_love.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_search.webp b/public/assets/tipImages/webp/baekgyeong_search.webp new file mode 100644 index 00000000..e870bb12 Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_search.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_suprised.webp b/public/assets/tipImages/webp/baekgyeong_suprised.webp new file mode 100644 index 00000000..aa2881cc Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_suprised.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_teach.webp b/public/assets/tipImages/webp/baekgyeong_teach.webp new file mode 100644 index 00000000..57de4586 Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_teach.webp differ diff --git a/public/assets/tipImages/webp/baekgyeong_underpin.webp b/public/assets/tipImages/webp/baekgyeong_underpin.webp new file mode 100644 index 00000000..feb62201 Binary files /dev/null and b/public/assets/tipImages/webp/baekgyeong_underpin.webp differ diff --git a/public/assets/tipImages/webp/pknu.webp b/public/assets/tipImages/webp/pknu.webp new file mode 100644 index 00000000..4e44b20b Binary files /dev/null and b/public/assets/tipImages/webp/pknu.webp differ diff --git a/src/App.tsx b/src/App.tsx index 975aada4..f7d013ef 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -25,7 +25,7 @@ const App = () => { } /> } /> } /> - } /> + } /> } /> }> diff --git a/src/components/Card/TipCard/TipImage.tsx b/src/components/Card/TipCard/TipImage.tsx new file mode 100644 index 00000000..10db07ed --- /dev/null +++ b/src/components/Card/TipCard/TipImage.tsx @@ -0,0 +1,32 @@ +import Image from '@components/Common/Image'; +import { css } from '@emotion/react'; +import React from 'react'; + +interface TipImageProps { + title: string; + webpPath: string; + pngPath: string; +} + +const TipImage = ({ title, webpPath, pngPath }: TipImageProps) => { + return ( + + + {title} + + ); +}; + +export default TipImage; diff --git a/src/components/Card/TipCard/TipSubTitle.tsx b/src/components/Card/TipCard/TipSubTitle.tsx new file mode 100644 index 00000000..d851bbb3 --- /dev/null +++ b/src/components/Card/TipCard/TipSubTitle.tsx @@ -0,0 +1,25 @@ +import styled from '@emotion/styled'; +import React from 'react'; + +interface TipSubTitleProps { + subTitle: string; +} + +const TipSubTitle = ({ subTitle }: TipSubTitleProps) => { + const seperatedSubTitle = subTitle.split('\n'); + return ( + + {seperatedSubTitle.map((subTitle, index) => ( +

{subTitle}

+ ))} +
+ ); +}; + +export default TipSubTitle; + +const SubTitle = styled.span` + padding: 0 0 0 16px; + line-height: 1rem; + font-size: 0.8rem; +`; diff --git a/src/components/Card/TipCard/TipTitle.tsx b/src/components/Card/TipCard/TipTitle.tsx new file mode 100644 index 00000000..d3b749f3 --- /dev/null +++ b/src/components/Card/TipCard/TipTitle.tsx @@ -0,0 +1,26 @@ +import styled from '@emotion/styled'; +import React from 'react'; + +interface TipTitleProps { + title: string; +} + +const TipTitle = ({ title }: TipTitleProps) => { + const seperatedTitle = title.split('\n'); + return ( + + {seperatedTitle.map((titleItem, index) => ( + <p key={index}>{titleItem}</p> + ))} + + ); +}; + +export default TipTitle; + +const Title = styled.span` + padding: 20px 0px 10px 16px; + line-height: 1.2rem; + font-size: 1.2rem; + font-weight: bold; +`; diff --git a/src/components/Card/TipCard/domain/getTipCardSubElement.ts b/src/components/Card/TipCard/domain/getTipCardSubElement.ts new file mode 100644 index 00000000..083e0174 --- /dev/null +++ b/src/components/Card/TipCard/domain/getTipCardSubElement.ts @@ -0,0 +1,21 @@ +import { Children, isValidElement } from 'react'; + +import TipImage from '../TipImage'; +import TipSubTitle from '../TipSubTitle'; +import TipTitle from '../TipTitle'; + +type TipCardChildType = typeof TipTitle | typeof TipSubTitle | typeof TipImage; + +const getTipCardSubElement = ( + children: React.ReactNode, + childType: TipCardChildType, +) => { + const chidrenArray = Children.toArray(children); + const targetChild = chidrenArray + .filter((child) => isValidElement(child) && child.type === childType) + .slice(0, 2); + + return targetChild; +}; + +export default getTipCardSubElement; diff --git a/src/components/Card/TipCard/index.tsx b/src/components/Card/TipCard/index.tsx new file mode 100644 index 00000000..6cc301b3 --- /dev/null +++ b/src/components/Card/TipCard/index.tsx @@ -0,0 +1,47 @@ +import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +import getTipCardSubElement from './domain/getTipCardSubElement'; +import TipImage from './TipImage'; +import TipSubTitle from './TipSubTitle'; +import TipTitle from './TipTitle'; + +type StrictPropsWithChildren = T & { + children: React.ReactNode; + onClick: () => void; +}; + +const TipCard = ({ children, onClick }: StrictPropsWithChildren) => { + const tipTitle = getTipCardSubElement(children, TipTitle); + const tipSubTitle = getTipCardSubElement(children, TipSubTitle); + const tipImage = getTipCardSubElement(children, TipImage); + + return ( + + {tipTitle} + {tipSubTitle} + {tipImage} + + ); +}; + +export default TipCard; + +TipCard.TipTitle = TipTitle; +TipCard.TipSubTitle = TipSubTitle; +TipCard.TipImage = TipImage; + +const Container = styled.div` + position: relative; + height: 10rem; + width: 10rem; + display: flex; + flex-direction: column; + background-color: ${THEME.PRIMARY}20; + border: 1px solid ${THEME.PRIMARY}30; + border-radius: 10px; + box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1); + gap: 5px; + z-index: 1; +`; diff --git a/src/components/Common/Image/index.tsx b/src/components/Common/Image/index.tsx index 519e1231..c4572406 100644 --- a/src/components/Common/Image/index.tsx +++ b/src/components/Common/Image/index.tsx @@ -7,7 +7,7 @@ const imageSize: ImageSize = { large: setSize(200), medium: setSize(150), small: setSize(100), - tiny: setSize(45), + tiny: setSize(80), }; const Image = ({ diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 91cccaf4..20f5140e 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,37 +1,33 @@ import Icon from '@components/Common/Icon'; -import SideBar from '@components/SideBar'; -import SideBarContent from '@components/SideBar/Content'; import styled from '@emotion/styled'; import useRoter from '@hooks/useRouter'; import { THEME } from '@styles/ThemeProvider/theme'; -import { useState } from 'react'; -import { useLocation } from 'react-router-dom'; const Header = () => { - const { routerTo, goBack } = useRoter(); - const [open, setOpen] = useState(false); - const location = useLocation(); + const { routerTo, goBack, currentPath } = useRoter(); + if (currentPath === '/map') return <>; - if (location.pathname === '/map') return <>; + const isNotHomePage = currentPath !== '/'; return ( - - - - routerTo('/')}>부림이 - - - - - + + {isNotHomePage && ( + + + + )} + routerTo('/')}>부림이 + ); }; export default Header; -const HeaderContainer = styled.div` +const Container = styled.section` + position: relative; display: flex; justify-content: center; + align-items: center; width: 100%; max-width: 480px; @@ -43,12 +39,9 @@ const HeaderContainer = styled.div` box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; `; -const HeaderWrapper = styled.div` - width: 90%; - height: 100%; - display: flex; - justify-content: space-between; - align-items: center; +const IconContainer = styled.div` + position: absolute; + left: 1rem; `; const Logo = styled.span` diff --git a/src/components/InformUpperLayout/InformSubTitle.tsx b/src/components/InformUpperLayout/InformSubTitle.tsx new file mode 100644 index 00000000..01d1110e --- /dev/null +++ b/src/components/InformUpperLayout/InformSubTitle.tsx @@ -0,0 +1,28 @@ +import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +interface InformSubTitleProps { + subTitle: string; +} + +const InformSubTitle = ({ subTitle }: InformSubTitleProps) => { + const seperatedSubTitle = subTitle.split('\n'); + + return ( + + {seperatedSubTitle.map((subTitle, index) => ( +

{subTitle}

+ ))} +
+ ); +}; + +export default InformSubTitle; + +const SubTitle = styled.span` + padding: 0 0 1rem 0; + color: ${THEME.TEXT.GRAY}; + line-height: 1.3; + font-size: 0.9rem; +`; diff --git a/src/components/InformUpperLayout/InformTitle.tsx b/src/components/InformUpperLayout/InformTitle.tsx new file mode 100644 index 00000000..6de18811 --- /dev/null +++ b/src/components/InformUpperLayout/InformTitle.tsx @@ -0,0 +1,20 @@ +import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +interface InformTitleProps { + title: string; +} + +const InformTitle = ({ title }: InformTitleProps) => { + return {title}; +}; + +export default InformTitle; + +const Title = styled.span` + padding: 1.5rem 0 1.5rem 0; + color: ${THEME.TEXT.BLACK}; + font-size: 1.5rem; + font-weight: bold; +`; diff --git a/src/components/InformUpperLayout/InformTypeButton.tsx b/src/components/InformUpperLayout/InformTypeButton.tsx new file mode 100644 index 00000000..59cc824d --- /dev/null +++ b/src/components/InformUpperLayout/InformTypeButton.tsx @@ -0,0 +1,35 @@ +import Button from '@components/Common/Button'; +import { css } from '@emotion/react'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +interface InformTypeButtonProps { + type: string; + isActive: boolean; + onClick: () => void; +} + +const InformTypeButton = ({ + type, + isActive, + onClick, +}: InformTypeButtonProps) => { + return ( + + ); +}; + +export default InformTypeButton; diff --git a/src/components/InformUpperLayout/domain/getInformUpperLayoutSubElement.ts b/src/components/InformUpperLayout/domain/getInformUpperLayoutSubElement.ts new file mode 100644 index 00000000..790baa3f --- /dev/null +++ b/src/components/InformUpperLayout/domain/getInformUpperLayoutSubElement.ts @@ -0,0 +1,24 @@ +import { Children, isValidElement } from 'react'; + +import InformSubTitle from '../InformSubTitle'; +import InformTitle from '../InformTitle'; +import InformTypeButton from '../InformTypeButton'; + +type InformUpperLayoutChildType = + | typeof InformTitle + | typeof InformSubTitle + | typeof InformTypeButton; + +const getInformUpperLayoutSubElement = ( + children: React.ReactNode, + childType: InformUpperLayoutChildType, +) => { + const childrenArray = Children.toArray(children); + const targetChild = childrenArray + .filter((child) => isValidElement(child) && child.type === childType) + .slice(0, 2); + + return targetChild; +}; + +export default getInformUpperLayoutSubElement; diff --git a/src/components/InformUpperLayout/index.tsx b/src/components/InformUpperLayout/index.tsx new file mode 100644 index 00000000..838d025e --- /dev/null +++ b/src/components/InformUpperLayout/index.tsx @@ -0,0 +1,49 @@ +import styled from '@emotion/styled'; +import React from 'react'; + +import getInformUpperLayoutSubElement from './domain/getInformUpperLayoutSubElement'; +import InformSubTitle from './InformSubTitle'; +import InformTitle from './InformTitle'; +import InformTypeButton from './InformTypeButton'; + +type StrictPropsWithChildren = T & { children: React.ReactNode }; + +const InformUpperLayout = ({ children }: StrictPropsWithChildren) => { + const informTitle = getInformUpperLayoutSubElement(children, InformTitle); + const informSubTitle = getInformUpperLayoutSubElement( + children, + InformSubTitle, + ); + const informTypeButton = getInformUpperLayoutSubElement( + children, + InformTypeButton, + ); + + return ( + + {informTitle} + {informSubTitle} + {informTypeButton && ( + {informTypeButton} + )} + + ); +}; + +export default InformUpperLayout; + +InformUpperLayout.InformTitle = InformTitle; +InformUpperLayout.InformSubTitle = InformSubTitle; +InformUpperLayout.InformTypeButton = InformTypeButton; + +const Container = styled.section` + padding: 0px 20px 0px 20px; + display: flex; + flex-direction: column; +`; + +const TypeButtonContainer = styled.div` + padding: 0 0 10px 0; + display: flex; + column-gap: 10px; +`; diff --git a/src/components/List/TipCardList/index.tsx b/src/components/List/TipCardList/index.tsx new file mode 100644 index 00000000..fa9805c5 --- /dev/null +++ b/src/components/List/TipCardList/index.tsx @@ -0,0 +1,21 @@ +import { TipData } from '@constants/tip'; +import styled from '@emotion/styled'; +import React from 'react'; + +interface TipCardListProps { + tipList: TipData[]; + tipItemRenderer: (tipItem: TipData) => JSX.Element; +} + +const TipCardList = ({ tipList, tipItemRenderer }: TipCardListProps) => { + return {tipList.map((tipItem) => tipItemRenderer(tipItem))}; +}; + +export default TipCardList; + +const Grid = styled.section` + display: grid; + padding: 0 20px 10px 20px; + grid-template-columns: 1fr auto; + gap: 10px; +`; diff --git a/src/components/SideBar/Content/index.tsx b/src/components/SideBar/Content/index.tsx deleted file mode 100644 index d0f5335f..00000000 --- a/src/components/SideBar/Content/index.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import Icon from '@components/Common/Icon'; -import SIDEBAR_CONTENT from '@constants/sidebar'; -import styled from '@emotion/styled'; -import useRouter from '@hooks/useRouter'; -import { THEME } from '@styles/ThemeProvider/theme'; -import React, { SetStateAction } from 'react'; - -interface SideBarContentProps { - setOpen: React.Dispatch>; -} - -const SideBarContent = ({ setOpen }: SideBarContentProps) => { - const { routerTo } = useRouter(); - const routerToPath = (path: string) => { - routerTo(path); - setOpen(false); - }; - - return ( - - {SIDEBAR_CONTENT.map((item) => { - return ( - routerToPath(item.path)}> - - {item.title} - - ); - })} - - ); -}; - -export default SideBarContent; - -const Container = styled.section` - display: flex; - flex-direction: column; - align-items: flex-start; - - line-height: 4; -`; - -const SideBarItem = styled.div` - width: 100%; - - font-size: 16px; - color: ${THEME.TEXT.BLACK}; - - display: flex; - align-items: center; - border-bottom: 1px solid ${THEME.BUTTON.GRAY}; -`; - -const Title = styled.span` - text-indent: 10px; -`; diff --git a/src/components/SideBar/index.tsx b/src/components/SideBar/index.tsx deleted file mode 100644 index af574ae9..00000000 --- a/src/components/SideBar/index.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import Icon from '@components/Common/Icon'; -import Image from '@components/Common/Image'; -import ASSET_PATH from '@constants/assets-path'; -import { css, keyframes } from '@emotion/react'; -import styled from '@emotion/styled'; -import { THEME } from '@styles/ThemeProvider/theme'; -import React, { CSSProperties, SetStateAction, useRef, useState } from 'react'; - -interface SideBarProps { - width?: CSSProperties['width']; - children: React.ReactNode; - open: boolean; - setOpen: React.Dispatch>; -} - -const SideBar = ({ width = '70%', children, open, setOpen }: SideBarProps) => { - const [mount, setMount] = useState(false); - const sideBarRef = useRef(null); - - const openSideBar = () => { - setMount(true); - setOpen(true); - }; - - const handleCloseSideBar = (e: React.MouseEvent) => { - if (e.target === e.currentTarget) { - setMount(false); - setTimeout(() => { - setOpen(false); - }, 300); - } - }; - - return ( - - - {open && ( - - - - 부림이 - {children} - - - )} - - ); -}; - -export default SideBar; - -const Container = styled.section` - max-width: 480px; - position: relative; - display: flex; - justify-content: flex-end; -`; - -const SideBarBackground = styled.div<{ mount: boolean }>` - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - display: flex; - justify-content: center; - align-items: center; - background-color: rgba(0, 0, 0, 0.6); - z-index: 9999; - - opacity: ${({ mount }) => (mount ? '1' : '0')}; - transition: opacity 0.3s ease-out; -`; - -interface SideBarContentProps { - width: CSSProperties['width']; - mount: boolean; -} - -const SideBarContent = styled.div` - position: fixed; - top: 0; - right: 0; - bottom: 0; - height: 100%; - width: ${({ width }) => width}; - padding: 12px; - background-color: ${THEME.IVORY}; - - display: flex; - flex-direction: column; - - animation: ${({ mount }) => (mount ? slideIn : slideOut)} 0.3s ease-out; -`; - -const Title = styled.span` - text-align: center; - font-size: 16px; -`; - -const slideIn = keyframes` - from { - opacity: 0; - transform: translateX(100%); - } - to { - opacity: 1; - transform: translateX(0%); - } -`; - -const slideOut = keyframes` - from { - opacity: 1; - transform: translateX(0%); - } - to { - opacity: 0; - transform: translateX(100%); - } -`; diff --git a/src/constants/assets-path.ts b/src/constants/assets-path.ts deleted file mode 100644 index 469e6e88..00000000 --- a/src/constants/assets-path.ts +++ /dev/null @@ -1,7 +0,0 @@ -const ASSET_PATH = { - WHALEBE: '/assets/baekgyeong-whalebe.png', - PKNU: 'assets/pknu.png', - ICON: '/assets/baekgyeong-speaker.png', -}; - -export default ASSET_PATH; diff --git a/src/constants/path.ts b/src/constants/path.ts index 45e2d1e6..eb5fa20b 100644 --- a/src/constants/path.ts +++ b/src/constants/path.ts @@ -9,6 +9,10 @@ const PATH = { `/announcement/${category}/pinned`, SEARCH_ANNOUNCEMENT: (category: Category, keyword: string) => `/announcement/${category}/search?q=${keyword}`, + TIP: { + SHORTCUT: '/tip/shortcut', + HONEY_TIP: '/tip/honeytip', + }, } as const; export default PATH; diff --git a/src/constants/tip.ts b/src/constants/tip.ts index 982e781e..4f29d101 100644 --- a/src/constants/tip.ts +++ b/src/constants/tip.ts @@ -1,52 +1,105 @@ -import { IconKind } from '@type/styles/icon'; - -import ASSET_PATH from './assets-path'; - -interface SideBarContent { - readonly id: number; - readonly title: string; - readonly path: string; - readonly iconKind?: IconKind; - readonly imagePath?: string; +export interface TipData { + title: string; + subTitle: string; + webpPath: string; + pngPath: string; + link: string; } -const TIP_CONTENT: SideBarContent[] = [ +export const SHORTCUT_DATA: readonly TipData[] = [ { - id: 1, title: '부경대학교', - path: 'https://www.pknu.ac.kr/main', - imagePath: `${ASSET_PATH.PKNU}`, + subTitle: '부경대학교\n홈페이지로 이동', + webpPath: '/assets/tipImages/webp/pknu.webp', + pngPath: '/assets/tipImages/png/pknu.png', + link: 'https://www.pknu.ac.kr/main', }, { - id: 2, title: '웨일비', - path: 'https://whalebe.pknu.ac.kr/main/1', - imagePath: `${ASSET_PATH.WHALEBE}`, + subTitle: '웨일비 비교과\n홈페이지로 이동', + webpPath: '/assets/tipImages/webp/baekgyeong_love.webp', + pngPath: '/assets/tipImages/png/baekgyeong_love.png', + link: 'https://whalebe.pknu.ac.kr/main', + }, + { + title: '진로취업\n길라잡이', + subTitle: '취업관련\n정보, 검사 하러가기', + webpPath: '/assets/tipImages/webp/baekgyeong_teach.webp', + pngPath: '/assets/tipImages/png/baekgyeong_teach.png', + link: 'https://pknujob.pknu.ac.kr/main', }, { - id: 3, - title: '진로취업길라잡이', - path: 'https://pknujob.pknu.ac.kr/main', - iconKind: 'handshake', + title: '증명서\n발급센터', + subTitle: '각종 증명서\n발급하러 가기', + webpPath: '/assets/tipImages/webp/baekgyeong_search.webp', + pngPath: '/assets/tipImages/png/baekgyeong_search.png', + link: 'https://pknu.certpia.com/', }, { - id: 4, - title: '증명서발급센터', - path: 'https://pknu.certpia.com/', - iconKind: 'print', + title: '이루미', + subTitle: '부경대 포털 사이트\n바로가기', + webpPath: '/assets/tipImages/webp/baekgyeong_teach.webp', + pngPath: '/assets/tipImages/png/baekgyeong_teach.png', + link: 'https://portal.pknu.ac.kr/', }, { - id: 5, - title: '강의계획서 조회', - path: 'https://irumi.pknu.ac.kr/nxui/launch.html?screenid=Desktop_screen_quick&menuId=U020913', - iconKind: 'document', + title: '도서관', + subTitle: '도서관 정보\n확인하기', + webpPath: '/assets/tipImages/webp/baekgyeong_camera.webp', + pngPath: '/assets/tipImages/png/baekgyeong_camera.png', + link: 'https://libweb.pknu.ac.kr/', + }, + { + title: '해커스', + subTitle: '토익, 스피킹 등\n외국어 무료 강좌', + webpPath: '/assets/tipImages/webp/baekgyeong_hi.webp', + pngPath: '/assets/tipImages/png/baekgyeong_hi.png', + link: 'https://pknulib.champstudy.com/', + }, +] as const; + +export const HONEY_TIP_DATA: readonly TipData[] = [ + { + title: '아우란트검사', + subTitle: '인성·역량·취업준비도\n·진로적성검사', + webpPath: '/assets/tipImages/webp/baekgyeong_hi.webp', + pngPath: '/assets/tipImages/png/baekgyeong_hi.png', + link: 'https://u.educe.co.kr/pknu', + }, + { + title: '동아리/스터디', + subTitle: '동아리/스터디\n모집 정보 알아보기', + webpPath: '/assets/tipImages/webp/baekgyeong_love.webp', + pngPath: '/assets/tipImages/png/baekgyeong_love.png', + link: 'https://www.pknu.ac.kr/main/143', }, { - id: 6, title: '아르바이트', - path: 'https://www.pknu.ac.kr/main/145', - iconKind: 'personSearch', + subTitle: '알바 정보 보러가기', + webpPath: '/assets/tipImages/webp/baekgyeong_camera.webp', + pngPath: '/assets/tipImages/png/baekgyeong_camera.png', + link: 'https://www.pknu.ac.kr/main/145', }, -]; + { + title: '강의계획서\n조회', + subTitle: '강의정보 열람하기', + webpPath: '/assets/tipImages/webp/baekgyeong_teach.webp', + pngPath: '/assets/tipImages/png/baekgyeong_teach.png', + link: 'https://irumi.pknu.ac.kr/nxui/launch.html?screenid=Desktop_screen_quick&menuId=U020913', + }, +] as const; + +export const TIP_TYPE = { + SHORTCUT: 'shortcut', + HONEY_TIP: 'honeytip', +} as const; -export default TIP_CONTENT; +export const TIP_PAGE = { + TITLE: '꿀팁 사이트', + SUB_TITLE: + '알아두면 쓸모 있는 학교 관련 정보 페이지들입니다.\n카드를 누르면 바로 사이트로 이동해요.', + BUTTON: { + SHORTCUT: '바로가기', + HONEY_TIP: '꿀팁', + }, +} as const; diff --git a/src/pages/Tip/index.tsx b/src/pages/Tip/index.tsx index 2e22085f..6b1c9ef1 100644 --- a/src/pages/Tip/index.tsx +++ b/src/pages/Tip/index.tsx @@ -1,40 +1,59 @@ -import Icon from '@components/Common/Icon'; -import Image from '@components/Common/Image'; -import TIP_CONTENT from '@constants/tip'; -import { css } from '@emotion/react'; +import TipCard from '@components/Card/TipCard'; +import InformUpperLayout from '@components/InformUpperLayout'; +import TipCardList from '@components/List/TipCardList'; +import PATH from '@constants/path'; +import { + HONEY_TIP_DATA, + SHORTCUT_DATA, + TIP_PAGE, + TIP_TYPE, + TipData, +} from '@constants/tip'; import styled from '@emotion/styled'; -import { THEME } from '@styles/ThemeProvider/theme'; +import useRouter from '@hooks/useRouter'; +import openLink from '@utils/router/openLink'; import React from 'react'; +import { useParams } from 'react-router-dom'; const Tip = () => { - const moveToPath = (path: string) => { - window.open(path, '_blank'); - }; + const { type } = useParams(); + if (!type) return <>; + + const { routerTo } = useRouter(); + const routerToShortcut = () => routerTo(PATH.TIP.SHORTCUT); + const routerToHoneyTip = () => routerTo(PATH.TIP.HONEY_TIP); + const tipList = type === TIP_TYPE.SHORTCUT ? SHORTCUT_DATA : HONEY_TIP_DATA; return ( - {TIP_CONTENT.map((item) => { - return ( - moveToPath(item.path)}> - {item.iconKind && ( - - - - )} - {item.imagePath && ( - - )} - {item.title} - - ); - })} + + + + + + + ( + openLink(tipItem.link)}> + + + + + )} + /> ); }; @@ -42,34 +61,6 @@ const Tip = () => { export default Tip; const Container = styled.section` - width: 80%; - height: 100%; display: flex; flex-direction: column; - justify-content: center; - margin: 0 auto; - - line-height: 4; - gap: 10px; -`; - -const IconContainer = styled.div` - display: flex; - border-radius: 50%; - background-color: ${THEME.PRIMARY}; - height: 45px; - width: 45px; - justify-content: center; - align-items: center; -`; - -const TipItem = styled.div` - display: flex; - justify-content: space-between; - align-items: center; - - background-color: ${THEME.IVORY}; - padding: 5px; - border-radius: 15px; - box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; `;