From 9d85a80a74aa29c5d4f6b59a49b40c1e92de8441 Mon Sep 17 00:00:00 2001 From: Lee sang Yeop Date: Fri, 13 Oct 2023 21:13:36 +0900 Subject: [PATCH 01/31] =?UTF-8?q?Style:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Card/AnnounceCard/index.tsx | 60 +++++++++++++++------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/components/Card/AnnounceCard/index.tsx b/src/components/Card/AnnounceCard/index.tsx index 073e9c4e..af7deb46 100644 --- a/src/components/Card/AnnounceCard/index.tsx +++ b/src/components/Card/AnnounceCard/index.tsx @@ -1,6 +1,7 @@ import Icon from '@components/Icon'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; +import useMajor from '@hooks/useMajor'; import { THEME } from '@styles/ThemeProvider/theme'; import { AnnounceItem } from '@type/announcement'; @@ -14,6 +15,8 @@ const AnnounceCard = ({ uploadDate, pinned = false, }: AnnounceCardProps) => { + const { major } = useMajor(); + const onClick = () => { window.open(link, '_blank'); }; @@ -23,17 +26,18 @@ const AnnounceCard = ({ return ( - {pinned && } - {title} - - {uploadDate} + + {pinned && } + {title} + + + + {major} + + {uploadDate} + + ); }; @@ -41,8 +45,8 @@ const AnnounceCard = ({ export default AnnounceCard; const Card = styled.div` - height: 28px; - padding: 10px; + min-height: 28px; + padding: 4px; display: flex; flex-direction: column; justify-content: center; @@ -52,19 +56,18 @@ const Card = styled.div` const ContentContainer = styled.div` display: flex; - align-items: center; + line-height: 1.5; + flex-direction: column; `; const AnnounceTitle = styled.span<{ pinned: boolean }>` + display: flex; + align-items: center; flex: 9; font-size: 15px; font-weight: ${({ pinned }) => (pinned ? 'bold' : 500)}; margin-left: ${({ pinned }) => (pinned ? '' : '28px')}; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - &: hover { cursor: pointer; } @@ -86,8 +89,29 @@ const AnnounceDate = styled.span` flex: 1; font-size: 10px; font-weight: bold; - text-align: end; white-space: nowrap; color: ${THEME.TEXT.GRAY}; `; + +const Contour = styled.div` + width: 90%; + padding-top: 5px; + margin: 0 auto; + border-bottom: 1px solid ${THEME.BACKGROUND}; +`; + +const FlexWrapper = styled.div` + display: flex; +`; + +const SubTitle = styled.div` + display: flex; + align-items: center; + padding: 5px 0 0 26px; +`; + +const Source = styled.div` + font-size: 11px; + color: gray; +`; From 311b520fb60b3bf85b3072003760faf7e1aecec7 Mon Sep 17 00:00:00 2001 From: Lee sang Yeop Date: Sun, 15 Oct 2023 17:26:35 +0900 Subject: [PATCH 02/31] =?UTF-8?q?Design:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20UI=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Card/AnnounceCard/index.tsx | 37 ++++++++++------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/components/Card/AnnounceCard/index.tsx b/src/components/Card/AnnounceCard/index.tsx index af7deb46..70d7a496 100644 --- a/src/components/Card/AnnounceCard/index.tsx +++ b/src/components/Card/AnnounceCard/index.tsx @@ -1,19 +1,17 @@ -import Icon from '@components/Icon'; -import { css } from '@emotion/react'; import styled from '@emotion/styled'; import useMajor from '@hooks/useMajor'; import { THEME } from '@styles/ThemeProvider/theme'; import { AnnounceItem } from '@type/announcement'; interface AnnounceCardProps extends AnnounceItem { - pinned?: boolean; + Author?: string; } const AnnounceCard = ({ title, link, uploadDate, - pinned = false, + Author, }: AnnounceCardProps) => { const { major } = useMajor(); @@ -27,14 +25,12 @@ const AnnounceCard = ({ - {pinned && } - {title} + {title} + 20{uploadDate} - {major} - - {uploadDate} + {Author ? Author : major} @@ -45,8 +41,7 @@ const AnnounceCard = ({ export default AnnounceCard; const Card = styled.div` - min-height: 28px; - padding: 4px; + min-height: 50px; display: flex; flex-direction: column; justify-content: center; @@ -55,18 +50,19 @@ const Card = styled.div` `; const ContentContainer = styled.div` + padding: 20px 0 20px 0; display: flex; line-height: 1.5; flex-direction: column; `; -const AnnounceTitle = styled.span<{ pinned: boolean }>` +const AnnounceTitle = styled.span` display: flex; align-items: center; flex: 9; - font-size: 15px; - font-weight: ${({ pinned }) => (pinned ? 'bold' : 500)}; - margin-left: ${({ pinned }) => (pinned ? '' : '28px')}; + font-size: 16px; + font-weight: 500; + margin-left: 28px; &: hover { cursor: pointer; @@ -86,17 +82,15 @@ const VertialSeparator = styled.div` `; const AnnounceDate = styled.span` - flex: 1; - font-size: 10px; - font-weight: bold; + font-size: 13px; white-space: nowrap; color: ${THEME.TEXT.GRAY}; + padding-right: 5px; `; const Contour = styled.div` width: 90%; - padding-top: 5px; margin: 0 auto; border-bottom: 1px solid ${THEME.BACKGROUND}; `; @@ -108,10 +102,11 @@ const FlexWrapper = styled.div` const SubTitle = styled.div` display: flex; align-items: center; - padding: 5px 0 0 26px; + padding: 10px 0 0 28px; `; const Source = styled.div` - font-size: 11px; + font-size: 13px; color: gray; + padding-left: 5px; `; From 5f293fc58181a91363929674f3b7feb2bcb10ec0 Mon Sep 17 00:00:00 2001 From: Lee sang Yeop Date: Sun, 15 Oct 2023 17:46:29 +0900 Subject: [PATCH 03/31] =?UTF-8?q?Test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EC=97=90=20=EC=A0=84=EC=97=AD=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EA=B0=92=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=B4=20=ED=94=84=EB=A1=9C=EB=B0=94?= =?UTF-8?q?=EC=9D=B4=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Card/AnnounceCard/index.test.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/Card/AnnounceCard/index.test.tsx b/src/components/Card/AnnounceCard/index.test.tsx index 6558704d..02d09044 100644 --- a/src/components/Card/AnnounceCard/index.test.tsx +++ b/src/components/Card/AnnounceCard/index.test.tsx @@ -1,4 +1,5 @@ import http from '@apis/http'; +import MajorProvider from '@components/MajorProvider'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { AnnounceItemList } from '@type/announcement'; @@ -34,7 +35,12 @@ describe('공지사항 카드 컴포넌트 테스트', () => { const { 고정, 일반 } = announceList; 일반.forEach(async (annouce) => { - render(, { wrapper: MemoryRouter }); + render( + + + , + { wrapper: MemoryRouter }, + ); }); const annouceCards = screen.getAllByTestId('card'); From 3bfca87b4898c205257fc6b6474986ad995991a9 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 15:48:56 +0900 Subject: [PATCH 04/31] =?UTF-8?q?Delete:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20.gitkeep=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/.gitkeep | 0 src/utils/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/constants/.gitkeep delete mode 100644 src/utils/.gitkeep diff --git a/src/constants/.gitkeep b/src/constants/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/utils/.gitkeep b/src/utils/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 875de9e7de876fe98ceef0265bf9909cc70432eb Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:00:30 +0900 Subject: [PATCH 05/31] =?UTF-8?q?Config:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B4=80=EB=A0=A8=20=ED=83=80=EC=9E=85=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 - AnnouncementCategory : 'shool', 'major'와 같이 공지사항 분류 타입을 설정 - AnnouncementType : '일반', '고정' 처럼 확인 가능한 공지사항의 분류 타입을 설정 --- src/@types/announcement.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/@types/announcement.ts b/src/@types/announcement.ts index db26c25f..451930ee 100644 --- a/src/@types/announcement.ts +++ b/src/@types/announcement.ts @@ -1,3 +1,8 @@ +import { + ANNOUNCEMENT_CATEGORY, + ANNOUNCEMENT_TYPE, +} from '@constants/announcement'; + type AnnounceItemType = '고정' | '일반'; export interface AnnounceItem { @@ -11,3 +16,9 @@ export interface AnnounceItem { export type AnnounceItemList = { [key in AnnounceItemType]: AnnounceItem[]; }; + +export type AnnouncementCategory = + (typeof ANNOUNCEMENT_CATEGORY)[keyof typeof ANNOUNCEMENT_CATEGORY]; + +export type AnnouncementType = + (typeof ANNOUNCEMENT_TYPE)[keyof typeof ANNOUNCEMENT_TYPE]; From c4b960d3dcff2f68a8ca4c5a5341e5b6fb25742f Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:02:41 +0900 Subject: [PATCH 06/31] =?UTF-8?q?Refactor:=20=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=ED=95=A8=EC=88=98=20=EB=B3=80=EA=B2=BD,?= =?UTF-8?q?=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컴포넌트 내부에서 정의한 onClick 메서드 대신, 유틸 함수 openLink 함수 사용 - 경계선을 표현하는 스타일 컴포넌트 이름 변경 -> Vertical, Horizon 으로 종류를 구분 --- src/components/Card/AnnounceCard/index.tsx | 58 ++++++++-------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/src/components/Card/AnnounceCard/index.tsx b/src/components/Card/AnnounceCard/index.tsx index 70d7a496..42346fbd 100644 --- a/src/components/Card/AnnounceCard/index.tsx +++ b/src/components/Card/AnnounceCard/index.tsx @@ -2,38 +2,33 @@ import styled from '@emotion/styled'; import useMajor from '@hooks/useMajor'; import { THEME } from '@styles/ThemeProvider/theme'; import { AnnounceItem } from '@type/announcement'; +import openLink from '@utils/router/openLink'; interface AnnounceCardProps extends AnnounceItem { - Author?: string; + author?: string; } const AnnounceCard = ({ title, link, uploadDate, - Author, + author, }: AnnounceCardProps) => { const { major } = useMajor(); - const onClick = () => { - window.open(link, '_blank'); - }; - uploadDate = uploadDate.slice(2); return ( - + openLink(link)} data-testid="card"> - - {title} - - + {title} + 20{uploadDate} - - {Author ? Author : major} - + + {author ? author : major} + - + ); }; @@ -45,8 +40,13 @@ const Card = styled.div` display: flex; flex-direction: column; justify-content: center; - color: ${THEME.TEXT.BLACK}; + + transition: 0.3s; + &:active { + transform: scale(0.95); + opacity: 0.6; + } `; const ContentContainer = styled.div` @@ -54,6 +54,8 @@ const ContentContainer = styled.div` display: flex; line-height: 1.5; flex-direction: column; + + gap: 10px; `; const AnnounceTitle = styled.span` @@ -62,20 +64,9 @@ const AnnounceTitle = styled.span` flex: 9; font-size: 16px; font-weight: 500; - margin-left: 28px; - - &: hover { - cursor: pointer; - } - - transition: 0.3s; - &:active { - transform: scale(0.95); - opacity: 0.6; - } `; -const VertialSeparator = styled.div` +const VertialBoundaryLine = styled.div` border-left: 1px solid gray; height: 12px; margin: 0 5px; @@ -89,20 +80,13 @@ const AnnounceDate = styled.span` padding-right: 5px; `; -const Contour = styled.div` - width: 90%; - margin: 0 auto; +const HorizonBoundaryLine = styled.div` border-bottom: 1px solid ${THEME.BACKGROUND}; `; -const FlexWrapper = styled.div` - display: flex; -`; - -const SubTitle = styled.div` +const SubContent = styled.div` display: flex; align-items: center; - padding: 10px 0 0 28px; `; const Source = styled.div` From ee30cb0ad40fcd4118175c1f1027124840f9ec7f Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:07:36 +0900 Subject: [PATCH 07/31] =?UTF-8?q?Refactor:=20url=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=EB=8B=A4=EB=A5=B8=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=EC=9D=84=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - prop으로 받는 type은 normal, pinned, search 셋 중 하나이며 type에 따라 다른 데이터를 사용해 렌더링 하도록 함 - search 같은 경우는 검색, 검색 결과를 확인, 검색 결과를 렌더링등 로직이 많기 때문에 AnnounceSearchList 컴포넌트를 추가로 구현 --- .../Card/AnnounceCard/AnnounceList/index.tsx | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/components/Card/AnnounceCard/AnnounceList/index.tsx b/src/components/Card/AnnounceCard/AnnounceList/index.tsx index d6f28700..ffdb7032 100644 --- a/src/components/Card/AnnounceCard/AnnounceList/index.tsx +++ b/src/components/Card/AnnounceCard/AnnounceList/index.tsx @@ -1,5 +1,10 @@ -import { AnnounceItemList } from '@type/announcement'; +import { ANNOUNCEMENT_TYPE } from '@constants/announcement'; +import styled from '@emotion/styled'; +import { AnnounceSearchList } from '@pages/Announcement/components'; +import { THEME } from '@styles/ThemeProvider/theme'; +import { AnnounceItemList, AnnouncementType } from '@type/announcement'; import { AxiosError, AxiosResponse } from 'axios'; +import { Fragment } from 'react'; import AnnounceCard from '..'; @@ -13,30 +18,44 @@ interface AnnounceListProps { resource: { read: () => Resource; }; + type: AnnouncementType; } -const AnnounceList = ({ resource }: AnnounceListProps) => { +const AnnounceList = ({ resource, type }: AnnounceListProps) => { const announceList: Resource = resource.read(); - if (announceList === null || announceList instanceof Error) { - return null; + return <>; } - const { 고정: pinned, 일반: normal } = announceList as AnnounceItemList; + + const { 고정: pinnedAnnouncement, 일반: normalAnnouncemnet } = + announceList as AnnounceItemList; return ( <> - {pinned.map((announce, idx) => ( -
- -
- ))} - {normal.map((announce, idx) => ( -
- -
- ))} + + {type === ANNOUNCEMENT_TYPE.NORMAL && + normalAnnouncemnet.map((announce, idx) => ( + + + + ))} + {type === ANNOUNCEMENT_TYPE.PINNED && + pinnedAnnouncement.map((announce, idx) => ( + + + + ))} + {type === ANNOUNCEMENT_TYPE.SEARCH && ( + + )} ); }; export default AnnounceList; + +const BoundaryLine = styled.div` + border-bottom: 1px solid ${THEME.TEXT.BLACK}; +`; From c4d5a2a99415545705ae6b85294e927c90d11415 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:08:06 +0900 Subject: [PATCH 08/31] =?UTF-8?q?Test:=20=EB=AA=A8=ED=82=B9=ED=95=98?= =?UTF-8?q?=EB=8A=94=20useMajor=20=ED=9B=85=EC=97=90=20graduationLink=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Card/InformCard/index.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Card/InformCard/index.test.tsx b/src/components/Card/InformCard/index.test.tsx index 0eda9a28..a32daa6b 100644 --- a/src/components/Card/InformCard/index.test.tsx +++ b/src/components/Card/InformCard/index.test.tsx @@ -43,12 +43,13 @@ const setMajorMock = (isRender: boolean) => { jest.mock('react', () => ({ ...jest.requireActual('react'), - useState: () => [mockMajor, mockSetMajor], + useState: () => [mockMajor, mockSetMajor, graduationLink], })); return { major: mockMajor, setMajor: mockSetMajor, + graduationLink, }; }; From dc2f6aeaa8f5280262dda089d22020b967704c7c Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:08:41 +0900 Subject: [PATCH 09/31] =?UTF-8?q?Style:=20InformCard=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Card/InformCard/index.tsx | 93 +++++++++--------------- 1 file changed, 36 insertions(+), 57 deletions(-) diff --git a/src/components/Card/InformCard/index.tsx b/src/components/Card/InformCard/index.tsx index 3261abaa..5d3e688f 100644 --- a/src/components/Card/InformCard/index.tsx +++ b/src/components/Card/InformCard/index.tsx @@ -23,9 +23,10 @@ const InformCard = ({ }: InformCardProps) => { const { major } = useMajor(); const { routerTo } = useRouter(); - const routerToMajorDecision = () => routerTo('/major-decision'); const { openModal, closeModal } = useModals(); + const routeToMajorDecisionPage = () => routerTo('/major-decision'); + const handleMajorModal = () => { if (!majorRequired || major) { onClick(); @@ -38,7 +39,7 @@ const InformCard = ({ onClose: () => closeModal(modals.alert), routerTo: () => { closeModal(modals.alert); - routerToMajorDecision(); + routeToMajorDecisionPage(); }, }); }; @@ -46,40 +47,13 @@ const InformCard = ({ return ( <> - -
- -
-
- - - {title} - - - {title} 보러가기 - - + + + + + {title} + {title} 보러가기 +
); @@ -89,33 +63,38 @@ export default InformCard; const Card = styled.div` display: flex; - flex-direction: row; + align-items: center; padding: 3% 1% 2% 0; - color: ${THEME.TEXT.GRAY}; - height: 70px; - - & > svg { - margin: 10px 0; - } - cursor: pointer; + height: 4rem; transition: all 0.2s ease-in-out; - &:active { - transform: scale(0.95); - opacity: 0.6; + span:nth-of-type(1) { + font-size: 12px; + color: ${THEME.TEXT.GRAY}; } -`; -const Wrapper = styled.div` - &:first-of-type { - display: flex; - align-items: center; + span:nth-of-type(2) { + font-size: 16px; + font-weight: bold; + color: ${THEME.TEXT.BLACK}; } +`; - &:nth-of-type(2) { - display: flex; - flex-direction: column; - padding: 4% 0 3% 3%; - } +const TextContainer = styled.div` + display: flex; + flex-direction: column; + gap: 5px; +`; + +const IconContainer = styled.div` + height: 45px; + width: 45px; + display: flex; + justify-content: center; + align-items: center; + margin-right: 10px; + + border-radius: 50%; + background-color: ${THEME.PRIMARY}; `; From 90fbb379b838001f8b9fcacdac546b246d13e1a6 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:09:15 +0900 Subject: [PATCH 10/31] =?UTF-8?q?Chore:=20css=20selector=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EB=9D=84=EC=96=B4=EC=93=B0=EA=B8=B0=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EB=A6=B0=ED=8A=B8=20=EC=97=90=EB=9F=AC=EB=A5=BC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Carousel/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Carousel/index.tsx b/src/components/Carousel/index.tsx index 58336a48..9ae046b2 100644 --- a/src/components/Carousel/index.tsx +++ b/src/components/Carousel/index.tsx @@ -67,7 +67,7 @@ const CarouselContainer = styled.div` padding: 1rem 0 1rem; width: 100%; margin: 0 auto; - &: hover { + &:hover { cursor: pointer; } `; @@ -100,7 +100,7 @@ const Button = styled.button` border-radius: 0.5rem; margin-top: 1rem; - &: hover { + &:hover { cursor: pointer; } `; From 9864252f88dc1f967cc98d7a109037c8a97f69cd Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:09:32 +0900 Subject: [PATCH 11/31] =?UTF-8?q?Test:=20=EB=AA=A8=ED=82=B9=ED=95=98?= =?UTF-8?q?=EB=8A=94=20useMajor=20=ED=9B=85=EC=97=90=20graduationLink=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/List/DepartmentList/index.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/List/DepartmentList/index.test.tsx b/src/components/List/DepartmentList/index.test.tsx index dadb8d8b..6a231171 100644 --- a/src/components/List/DepartmentList/index.test.tsx +++ b/src/components/List/DepartmentList/index.test.tsx @@ -31,6 +31,7 @@ jest.mock('@hooks/useModals', () => { }); describe.skip('학과선택 테스트', () => { + const mockGraduationLink = 'https://ce.pknu.ac.kr/ce/2889'; const mockUseMajor = useMajor as jest.MockedFunction; const mockSetMajor = jest.fn(); @@ -38,6 +39,7 @@ describe.skip('학과선택 테스트', () => { mockUseMajor.mockReturnValue({ setMajor: mockSetMajor, major: '컴퓨터공학과', + graduationLink: mockGraduationLink, }); }); From fc159c66150017f733af621be07f55660e682c6c Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:11:36 +0900 Subject: [PATCH 12/31] =?UTF-8?q?Refactor:=20MajorProvider=EA=B0=80=20grad?= =?UTF-8?q?uationLink=EB=8F=84=20=EC=B1=85=EC=9E=84=20=EC=A7=80=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 전공 컨텍스트에서 전공과 관련되어 있는 졸업요건 링크도 책임을 져야 한다고 판단 --- src/components/MajorProvider/index.tsx | 33 +++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/components/MajorProvider/index.tsx b/src/components/MajorProvider/index.tsx index 7bc2feaf..b60ac618 100644 --- a/src/components/MajorProvider/index.tsx +++ b/src/components/MajorProvider/index.tsx @@ -1,36 +1,41 @@ +import http from '@apis/http'; import MajorContext from '@contexts/major'; +import { AxiosResponse } from 'axios'; import React, { useEffect, useState } from 'react'; +interface GraduationLink { + department: string; + link: string | null; +} + interface MajorProviderProps { children: React.ReactNode; } const MajorProvider = ({ children }: MajorProviderProps) => { const [major, setMajor] = useState(null); + const [graduationLink, setGraduationLink] = useState(''); useEffect(() => { const storedMajor = localStorage.getItem('major'); - if (!storedMajor) return; setMajor(storedMajor); }, []); useEffect(() => { - const handleStorageChange = (event: StorageEvent) => { - if (event.key === 'major') { - const storedMajor = event.newValue; - if (storedMajor !== null) setMajor(storedMajor); - } - }; - window.addEventListener('storage', handleStorageChange); - - return () => { - window.removeEventListener('storage', handleStorageChange); - }; - }, []); + if (!major) return; + + (async () => { + const response: AxiosResponse = await http.get( + `/api/graduation?major=${major}`, + ); + const graduationLink = response.data.link; + setGraduationLink(graduationLink); + })(); + }, [major]); return ( - + {children} ); From fc8d60791c9867253535a1c262965b65b066880e Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:12:02 +0900 Subject: [PATCH 13/31] =?UTF-8?q?Style:=20ConfirmModal=20=EB=84=A4,=20?= =?UTF-8?q?=EC=95=84=EB=8B=88=EC=98=A4=20=EC=9C=84=EC=B9=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Modal/ConfirmModal/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Modal/ConfirmModal/index.tsx b/src/components/Modal/ConfirmModal/index.tsx index 161f3536..d0016eb3 100644 --- a/src/components/Modal/ConfirmModal/index.tsx +++ b/src/components/Modal/ConfirmModal/index.tsx @@ -41,8 +41,8 @@ const ConfirmModal = ({ justify-content: center; `} > - + From 0737cb073b3f323ab5f4bc037700379e46db54aa Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:13:29 +0900 Subject: [PATCH 14/31] =?UTF-8?q?Config:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B4=80=EB=A0=A8=20=EC=83=81=EC=88=98=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 - TITLE: 공지사항 제목 - CATEGORY: 공지사항 분류, 어학 취업정보가 추가될 경우 여기에 추가할 수 있도록 함 - TYPE: API를 통해 가져온 공지사항을 분류 --- src/constants/announcement.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/constants/announcement.ts diff --git a/src/constants/announcement.ts b/src/constants/announcement.ts new file mode 100644 index 00000000..0b8e547a --- /dev/null +++ b/src/constants/announcement.ts @@ -0,0 +1,15 @@ +export const ANNOUNCEMENT_TITLE = { + SCHOOL: '학교 공지사항', + MAROR: '학과 공지사항', +}; + +export const ANNOUNCEMENT_CATEGORY = { + SCHOOL: 'school', + MAJOR: 'major', +} as const; + +export const ANNOUNCEMENT_TYPE = { + NORMAL: 'normal', + PINNED: 'pinned', + SEARCH: 'search', +} as const; From 8a2739e2076957736b60025d4d2a7e39910ca21b Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:14:23 +0900 Subject: [PATCH 15/31] =?UTF-8?q?Config:=20=EA=B2=BD=EB=A1=9C=EB=93=A4?= =?UTF-8?q?=EC=9D=84=20=EC=83=81=EC=88=98=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 아직 상수로 빼지 못한 path들은 이 후 작업에서 빼도록 함 --- src/constants/path.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/constants/path.ts diff --git a/src/constants/path.ts b/src/constants/path.ts new file mode 100644 index 00000000..45e2d1e6 --- /dev/null +++ b/src/constants/path.ts @@ -0,0 +1,14 @@ +type Category = 'school' | 'major'; + +const PATH = { + SCHOOL_ANNOUNCEMENT: '/school/:type', + MAJOR_ANNOUNCEMENT: '/major/:type', + NORMAL_ANNOUNCEMENT: (category: Category) => + `/announcement/${category}/normal`, + PINNED_ANNOUNCEMENT: (category: Category) => + `/announcement/${category}/pinned`, + SEARCH_ANNOUNCEMENT: (category: Category, keyword: string) => + `/announcement/${category}/search?q=${keyword}`, +} as const; + +export default PATH; From 5b987fe12d19cdc7aa6a247114fe3ae76e3f03c0 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:14:45 +0900 Subject: [PATCH 16/31] =?UTF-8?q?Chore:=20placeholder=EC=97=90=20=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=EC=82=AC=ED=95=AD=20=EA=B2=80=EC=83=89=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/constants/placeholder-message.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants/placeholder-message.ts b/src/constants/placeholder-message.ts index 3ad0c513..553ee67a 100644 --- a/src/constants/placeholder-message.ts +++ b/src/constants/placeholder-message.ts @@ -1,6 +1,7 @@ const PLCACEHOLDER_MESSAGES = { SUGGESTION: '건의사항을 5글자 이상 남겨주세요', SEARCH_BUILDING: '건물번호 또는 건물이름을 검색해주세요', + SEARCH_TITLE: '제목을 검색하세요', } as const; export default PLCACEHOLDER_MESSAGES; From ac95f84b4640d225ba1868b7d9c98c94628ecb03 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:15:05 +0900 Subject: [PATCH 17/31] =?UTF-8?q?Chore:=20=ED=86=A0=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=EC=97=90=20=EA=B3=B5=EC=A7=80?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EA=B2=80=EC=83=89=20=ED=82=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EC=97=86=EC=9D=84=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20=EB=A9=94=EC=84=B8=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/constants/toast-message.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/constants/toast-message.ts b/src/constants/toast-message.ts index bef46bad..08f04ef3 100644 --- a/src/constants/toast-message.ts +++ b/src/constants/toast-message.ts @@ -1,7 +1,8 @@ const TOAST_MESSAGES = { OUT_OF_BOUNDARY: '학교 외부로 이동할 수 없어요!', OUT_OF_SHOOL: '학교 밖에서는 내 위치 정보를 제공하지 않아요!', - SHARE_LOCATION: '위치 정보를 공유해 주세요.', + SHARE_LOCATION: '위치 정보를 공유해 주세요', + SEARCH_KEYWORD: '검색어를 입력해주세요', } as const; export default TOAST_MESSAGES; From 394655b5278c1fa5439bcc23c52f6a1b060f7177 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:15:39 +0900 Subject: [PATCH 18/31] =?UTF-8?q?Refactor:=20MajorContext=EC=97=90=20gradu?= =?UTF-8?q?ationLink=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/contexts/major.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/contexts/major.ts b/src/contexts/major.ts index 750de426..4cf8a5be 100644 --- a/src/contexts/major.ts +++ b/src/contexts/major.ts @@ -4,6 +4,7 @@ import { createContext } from 'react'; interface MajorState { major: Major; setMajor: React.Dispatch>; + graduationLink: string | null; } const MajorContext = createContext(null); From c4ee69502f7c9dfbb62af49913d6c171714421e7 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:18:03 +0900 Subject: [PATCH 19/31] =?UTF-8?q?Refactor:=20Announcement=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=8A=94=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=8C=85=20=EC=B1=85=EC=9E=84=EB=A7=8C=20=EC=A7=80=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - announcement// 에 따라서 컴포넌트를 렌더링 하도록 함 --- src/pages/Announcement/index.tsx | 155 ++++++------------------------- 1 file changed, 30 insertions(+), 125 deletions(-) diff --git a/src/pages/Announcement/index.tsx b/src/pages/Announcement/index.tsx index 69c17be7..4044c138 100644 --- a/src/pages/Announcement/index.tsx +++ b/src/pages/Announcement/index.tsx @@ -1,136 +1,41 @@ -import fetchAnnounceList from '@apis/Suspense/fetch-announce-list'; -import Button from '@components/Button'; -import AnnounceList from '@components/Card/AnnounceCard/AnnounceList'; -import AnnounceCardSkeleton from '@components/Card/AnnounceCard/Skeleton'; -import { MODAL_BUTTON_MESSAGE, MODAL_MESSAGE } from '@constants/modal-messages'; -import { css, keyframes } from '@emotion/react'; -import styled from '@emotion/styled'; +import { + ANNOUNCEMENT_CATEGORY, + ANNOUNCEMENT_TITLE, +} from '@constants/announcement'; +import PATH from '@constants/path'; import useMajor from '@hooks/useMajor'; -import useModals, { modals } from '@hooks/useModals'; -import useRouter from '@hooks/useRouter'; -import { THEME } from '@styles/ThemeProvider/theme'; -import { Suspense } from 'react'; +import React from 'react'; +import { Route, Routes } from 'react-router-dom'; + +import { AnnounceContainer } from './components'; const Announcement = () => { const { major } = useMajor(); - const { routerTo } = useRouter(); - const { openModal, closeModal } = useModals(); - - const announceKeyword = decodeURI(window.location.pathname.split('/')[2]); - const isActiveSchoolAnnouncement = () => announceKeyword === 'undefined'; - - const routerToMajorDecision = () => routerTo('/major-decision'); - const routerToSchoolAnnouncement = () => routerTo(''); - const routerToMajorAnnouncement = () => { - if (!major) { - openModal(modals.alert, { - message: MODAL_MESSAGE.ALERT.SET_MAJOR, - buttonMessage: MODAL_BUTTON_MESSAGE.SET_MAJOR, - iconKind: 'plus', - onClose: () => closeModal(modals.alert), - routerTo: () => { - closeModal(modals.alert); - routerToMajorDecision(); - }, - }); - } - routerTo(`${major}`); - }; return ( - - - - - - - - }> - + - - - + } + /> + + } + /> + ); }; export default Announcement; - -const Container = styled.div` - overflow-x: hidden; -`; - -const ButtonContainer = styled.div` - width: 100%; - display: flex; - position: relative; - overflow-x: none; -`; - -const ButtonBottomBar = styled.span<{ isActiveSchool: boolean }>` - &:before { - content: ''; - position: absolute; - bottom: 0; - left: ${({ isActiveSchool }) => (isActiveSchool ? '0' : '50%')}; - width: 50%; - height: 3px; - background-color: ${THEME.PRIMARY}; - transition: left 0.3s ease-in-out; - } -`; - -const AnnounceContainer = styled.div<{ isActiveSchool: boolean }>` - width: 100%; - overflow: hidden; - animation: ${({ isActiveSchool }) => - isActiveSchool ? AnnounceSlideLeft : AnnounceSlideRight} - 0.3s forwards; -`; - -const AnnounceSlideRight = keyframes` - from { - transform: translateX(-100%); - } - to { - transform: translateX(0%); - } -`; - -const AnnounceSlideLeft = keyframes` - from { - transform: translateX(100%); - } - to { - transform: translateX(0%); - } -`; From d774d20fad9e9357ed6a7549ac3285b469fb5a7f Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:21:40 +0900 Subject: [PATCH 20/31] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=ED=84=B4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - title : 공지사항 제목을 표현 ex) 학교 공지사항 - category : 공지사항 분류를 표현 ex) announcement/school -> 학교 공지사항 - endPoint : 공지사항을 가져오기 위한 api endPoint를 표현 - 이 3가지 props만 전달하면 검색, 일반 & 공지 필터링, 공지사항 리스트 렌더링을 책임지는 컴포넌트를 렌더링 할 수 있음 --- .../components/AnnounceContainer.tsx | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/pages/Announcement/components/AnnounceContainer.tsx diff --git a/src/pages/Announcement/components/AnnounceContainer.tsx b/src/pages/Announcement/components/AnnounceContainer.tsx new file mode 100644 index 00000000..dd8bedce --- /dev/null +++ b/src/pages/Announcement/components/AnnounceContainer.tsx @@ -0,0 +1,120 @@ +import fetchAnnounceList from '@apis/Suspense/fetch-announce-list'; +import AnnounceList from '@components/Card/AnnounceCard/AnnounceList'; +import AnnounceCardSkeleton from '@components/Card/AnnounceCard/Skeleton'; +import { ANNOUNCEMENT_TYPE } from '@constants/announcement'; +import PATH from '@constants/path'; +import { keyframes } from '@emotion/react'; +import styled from '@emotion/styled'; +import useRouter from '@hooks/useRouter'; +import { + AnnounceItemList, + AnnouncementCategory, + AnnouncementType, +} from '@type/announcement'; +import React, { Suspense, useMemo } from 'react'; +import { useParams } from 'react-router-dom'; + +import AnnounceSearch from './AnnounceSearch'; +import AnnounceTypeButtons from './AnnounceTypeButtons'; + +interface AnnounceContainerProps { + title: string; + category: AnnouncementCategory; + endPoint: string | null; +} + +const AnnounceContainer = ({ + title, + category, + endPoint, +}: AnnounceContainerProps) => { + const { type } = useParams(); + if (!type) return <>; + + const { routerTo } = useRouter(); + + const showNormalAnnouncement = () => + routerTo(PATH.NORMAL_ANNOUNCEMENT(category)); + const showPinnedAnnouncement = () => + routerTo(PATH.PINNED_ANNOUNCEMENT(category)); + + const resource = useMemo( + () => fetchAnnounceList(endPoint), + [], + ); + + return ( + + {title} + + + + + + + }> + + + + + ); +}; + +export default AnnounceContainer; + +const Container = styled.div` + overflow-x: hidden; + display: flex; + flex-direction: column; + + row-gap: 15px; + padding: 10px; +`; + +const AnnounceTitle = styled.span` + margin-top: 1rem; + font-size: 1.5rem; + font-weight: bold; +`; + +const ButtonContainer = styled.div` + display: flex; + column-gap: 10px; +`; + +const getAnimationType = (type: AnnouncementType) => { + if (type === 'search') return 'none'; + return type === 'normal' ? AnnounceSlideLeft : AnnounceSlideRight; +}; + +const AnnounceListContainer = styled.div<{ type: AnnouncementType }>` + width: 100%; + overflow: hidden; + animation: ${({ type }) => getAnimationType(type)} 0.3s forwards; +`; + +const AnnounceSlideRight = keyframes` + from { + transform: translateX(-100%); + } + to { + transform: translateX(0%); + } +`; + +const AnnounceSlideLeft = keyframes` + from { + transform: translateX(100%); + } + to { + transform: translateX(0%); + } +`; From 2611491bd5822c439e427da0aefd1831d3de8762 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:21:59 +0900 Subject: [PATCH 21/31] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B2=80=EC=83=89=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/AnnounceSearch.tsx | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/pages/Announcement/components/AnnounceSearch.tsx diff --git a/src/pages/Announcement/components/AnnounceSearch.tsx b/src/pages/Announcement/components/AnnounceSearch.tsx new file mode 100644 index 00000000..79cca090 --- /dev/null +++ b/src/pages/Announcement/components/AnnounceSearch.tsx @@ -0,0 +1,86 @@ +import Icon from '@components/Icon'; +import PATH from '@constants/path'; +import PLCACEHOLDER_MESSAGES from '@constants/placeholder-message'; +import TOAST_MESSAGES from '@constants/toast-message'; +import styled from '@emotion/styled'; +import useRouter from '@hooks/useRouter'; +import useToasts from '@hooks/useToast'; +import React, { useRef } from 'react'; + +interface AnnounceSearchProps { + category: 'school' | 'major'; +} + +const AnnounceSearch = ({ category }: AnnounceSearchProps) => { + const { routerTo } = useRouter(); + const { addToast } = useToasts(); + + const inputRef = useRef(null); + + const handleSubmit = (e: React.FormEvent) => { + if (!inputRef.current) return; + e.preventDefault(); + if (inputRef.current.value.length === 0) { + addToast(TOAST_MESSAGES.SEARCH_KEYWORD); + return; + } + + routerTo(PATH.SEARCH_ANNOUNCEMENT(category, inputRef.current.value)); + inputRef.current.value = ''; + inputRef.current.blur(); + }; + + return ( +
+ + + handleSubmit}> + + + +
+ ); +}; + +export default AnnounceSearch; + +const StyledForm = styled.form` + display: flex; + position: relative; +`; + +const StyledInput = styled.input` + -webkit-appearance: none; + appearance: none; + + width: 100%; + padding: 10px; + border: 0; + border-radius: 15px; + background-color: #7a9dd30f; + color: #7a9dd366; + font-size: 14px; + text-indent: 5px; + + &::placeholder { + color: #7a9dd366; + font-size: 14px; + } + box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.15); + &:focus { + outline: none; + box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.2); + } +`; + +const StyledIconWrapper = styled.button` + position: absolute; + right: 0.5rem; + top: 50%; + transform: translateY(-50%); + background-color: transparent; +`; From f95add6b9e5c9c93c93f6c2e0f7ae830b00b4b75 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:22:19 +0900 Subject: [PATCH 22/31] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B2=80=EC=83=89=20=EA=B2=B0=EA=B3=BC=20=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/AnnounceSearchList.tsx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/pages/Announcement/components/AnnounceSearchList.tsx diff --git a/src/pages/Announcement/components/AnnounceSearchList.tsx b/src/pages/Announcement/components/AnnounceSearchList.tsx new file mode 100644 index 00000000..26089384 --- /dev/null +++ b/src/pages/Announcement/components/AnnounceSearchList.tsx @@ -0,0 +1,55 @@ +import AnnounceCard from '@components/Card/AnnounceCard'; +import Icon from '@components/Icon'; +import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; +import { AnnounceItem } from '@type/announcement'; +import React, { Fragment } from 'react'; +import { useLocation } from 'react-router-dom'; + +interface AnnounceSearchProps { + announceList: AnnounceItem[]; +} + +const AnnounceSearchList = ({ announceList }: AnnounceSearchProps) => { + const { search } = useLocation(); + + const searchKeyword = decodeURI(search.split('=')[1]); + const searchResult = announceList.filter((announceItem) => + announceItem.title.includes(searchKeyword), + ); + const hasSearchResult = () => searchResult.length === 0; + + return ( + + {hasSearchResult() ? ( + searchResult.map((announce, idx) => ( + + + + )) + ) : ( + + + + {`"${searchKeyword}"`}에 관한 공지사항이 없습니다. + + + )} + + ); +}; + +export default AnnounceSearchList; + +const AnnounceNotFound = styled.div` + height: 20rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; +`; + +const NotFoundTitle = styled.span` + color: ${THEME.TEXT.GRAY}; +`; From adb21aef7b305c03753eac6f7c17d26524f21cb5 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:22:55 +0900 Subject: [PATCH 23/31] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=A7=80=20&=20?= =?UTF-8?q?=EC=9D=BC=EB=B0=98=20=EA=B5=AC=EB=B6=84=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/AnnounceTypeButtons.tsx | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/pages/Announcement/components/AnnounceTypeButtons.tsx diff --git a/src/pages/Announcement/components/AnnounceTypeButtons.tsx b/src/pages/Announcement/components/AnnounceTypeButtons.tsx new file mode 100644 index 00000000..1b309767 --- /dev/null +++ b/src/pages/Announcement/components/AnnounceTypeButtons.tsx @@ -0,0 +1,35 @@ +import Button from '@components/Button'; +import { css } from '@emotion/react'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +interface AnnounceTypeButtonsProps { + type: '일반' | '고정'; + isActive: boolean; + onClick: () => void; +} + +const AnnounceTypeButtons = ({ + type, + isActive, + onClick, +}: AnnounceTypeButtonsProps) => { + return ( + + ); +}; + +export default AnnounceTypeButtons; From 6d33105a82fcfd55157ff3c36b77b1cfc7e1367a Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:23:17 +0900 Subject: [PATCH 24/31] =?UTF-8?q?Chore:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A5=BC=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1=ED=95=98=EB=8A=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=ED=95=9C=EB=B2=88=EC=97=90=20export?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Announcement/components/index.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/pages/Announcement/components/index.ts diff --git a/src/pages/Announcement/components/index.ts b/src/pages/Announcement/components/index.ts new file mode 100644 index 00000000..2bce755e --- /dev/null +++ b/src/pages/Announcement/components/index.ts @@ -0,0 +1,4 @@ +export { default as AnnounceContainer } from './AnnounceContainer'; +export { default as AnnounceSearch } from './AnnounceSearch'; +export { default as AnnounceSearchList } from './AnnounceSearchList'; +export { default as AnnounceTypeButtons } from './AnnounceTypeButtons'; From a4ef78999c1f9d08b17bf1ea2aa130f8f59faac2 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:23:41 +0900 Subject: [PATCH 25/31] =?UTF-8?q?Test:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home/Home.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Home/Home.test.tsx b/src/pages/Home/Home.test.tsx index 4a962a09..1cc65f48 100644 --- a/src/pages/Home/Home.test.tsx +++ b/src/pages/Home/Home.test.tsx @@ -6,7 +6,7 @@ import '@testing-library/jest-dom'; import Home from './index'; -describe('App 컴포넌트 테스트', () => { +describe('Home Page 컴포넌트 테스트', () => { it('페이지에 공지사항 및 졸업요건 컴포넌트가 렌더링된다.', () => { render( @@ -18,7 +18,7 @@ describe('App 컴포넌트 테스트', () => { wrapper: MemoryRouter, }, ); - const notificationText = screen.getByText('공지사항'); + const notificationText = screen.getByText('학교 공지사항'); expect(notificationText).toBeInTheDocument(); const requirementText = screen.getByText('졸업요건'); From bec98e356e879c63bed5c542fa06eea64a5f3643 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:25:38 +0900 Subject: [PATCH 26/31] =?UTF-8?q?Refactor:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - InformCardList: 공지사항 관련 카드 컴포넌트를 추상화 - 홈페이지 컴포넌트에서 담당하던 graduationLink의 상태 관리를 MajorPovider로 이전 --- src/pages/Home/index.tsx | 45 +++------------------------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index e4eff870..5bbe61b6 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,49 +1,15 @@ -import http from '@apis/http'; -import InformCard from '@components/Card/InformCard'; import Carousel from '@components/Carousel'; import styled from '@emotion/styled'; -import useMajor from '@hooks/useMajor'; -import useRouter from '@hooks/useRouter'; import { THEME } from '@styles/ThemeProvider/theme'; -import { AxiosResponse } from 'axios'; -import { useEffect, useState } from 'react'; -const Home = () => { - const [graduationLink, setGraduationLink] = useState(''); - const { routerTo } = useRouter(); - const { major } = useMajor(); - - const routerToGraduationRequiredPage = (graduationLink: string | null) => { - graduationLink && window.open(graduationLink, '_blank'); - }; - - useEffect(() => { - if (!major) return; - const getGraduationLink = async () => { - const response: AxiosResponse = await http.get( - `/api/graduation?major=${major}`, - ); - setGraduationLink(response.data.link); - }; - getGraduationLink(); - }, [major]); +import InformCardList from './components/InformCardList'; +const Home = () => { return ( 학교 - routerTo('/announcement')} - /> - routerToGraduationRequiredPage(graduationLink)} - /> + 비교과 @@ -76,8 +42,3 @@ const InformTitle = styled.div` font-size: 20px; font-weight: bold; `; - -interface GraduationLink { - department: string; - link: string | null; -} From b26cbc157908d70c65958a7effa0ad704cf4c84f Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:26:01 +0900 Subject: [PATCH 27/31] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B4=80=EB=A0=A8=20=EC=B9=B4=EB=93=9C=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EB=AC=B6=EC=9D=80=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home/components/InformCardList.tsx | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/pages/Home/components/InformCardList.tsx diff --git a/src/pages/Home/components/InformCardList.tsx b/src/pages/Home/components/InformCardList.tsx new file mode 100644 index 00000000..e7102cba --- /dev/null +++ b/src/pages/Home/components/InformCardList.tsx @@ -0,0 +1,37 @@ +import InformCard from '@components/Card/InformCard'; +import { ANNOUNCEMENT_TITLE } from '@constants/announcement'; +import PATH from '@constants/path'; +import useMajor from '@hooks/useMajor'; +import useRouter from '@hooks/useRouter'; +import openLink from '@utils/router/openLink'; +import React from 'react'; + +const InformCardList = () => { + const { graduationLink } = useMajor(); + const { routerTo } = useRouter(); + + return ( + <> + routerTo(PATH.NORMAL_ANNOUNCEMENT('school'))} + /> + routerTo(PATH.NORMAL_ANNOUNCEMENT('major'))} + /> + openLink(graduationLink)} + /> + + ); +}; + +export default InformCardList; From dc62ac5b4f9ee1e697991b91583dab79685d25d9 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:26:16 +0900 Subject: [PATCH 28/31] =?UTF-8?q?Test:=20=EB=AA=A8=ED=82=B9=ED=95=98?= =?UTF-8?q?=EB=8A=94=20useMajor=20=ED=9B=85=EC=97=90=20graduationLink=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/MajorDecision/index.test.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pages/MajorDecision/index.test.tsx b/src/pages/MajorDecision/index.test.tsx index 9793ddf2..301c8177 100644 --- a/src/pages/MajorDecision/index.test.tsx +++ b/src/pages/MajorDecision/index.test.tsx @@ -15,7 +15,9 @@ jest.mock('react-router-dom', () => ({ })); describe.skip('학과선택 페이지 로직 테스트', () => { + const mockGraduationLink = 'https://ce.pknu.ac.kr/ce/2889'; const mockSetMajor = jest.fn(); + beforeEach(() => { jest.mock('react', () => ({ ...jest.requireActual('react'), @@ -30,7 +32,13 @@ describe.skip('학과선택 페이지 로직 테스트', () => { it('전공 선택 버튼 클릭 후, 상태 변경 테스트', async () => { render( - + , From af319f7d9b9900fcfe5e0a739b6590d6fcf233ca Mon Sep 17 00:00:00 2001 From: hwinkr Date: Sat, 4 Nov 2023 16:26:31 +0900 Subject: [PATCH 29/31] =?UTF-8?q?Feat:=20=EB=A7=81=ED=81=AC=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=8B=9C=ED=82=A4=EB=8A=94=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/router/openLink.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/utils/router/openLink.ts diff --git a/src/utils/router/openLink.ts b/src/utils/router/openLink.ts new file mode 100644 index 00000000..0a0bd152 --- /dev/null +++ b/src/utils/router/openLink.ts @@ -0,0 +1,5 @@ +export default function openLink(link: string | null) { + if (!link) return; + + window.open(link, '_blank'); +} From 31b547c67d2184cf7b50e8166bd552546588318f Mon Sep 17 00:00:00 2001 From: hwinkr Date: Fri, 17 Nov 2023 00:15:44 +0900 Subject: [PATCH 30/31] =?UTF-8?q?Feat:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B2=80=EC=83=89=20=EA=B2=B0=EA=B3=BC=EA=B0=80=20?= =?UTF-8?q?=EC=97=86=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=EB=B3=B4=EC=97=AC=20?= =?UTF-8?q?=EC=A4=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/AnnounceNotFound.tsx | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/pages/Announcement/components/AnnounceNotFound.tsx diff --git a/src/pages/Announcement/components/AnnounceNotFound.tsx b/src/pages/Announcement/components/AnnounceNotFound.tsx new file mode 100644 index 00000000..4a7def4a --- /dev/null +++ b/src/pages/Announcement/components/AnnounceNotFound.tsx @@ -0,0 +1,32 @@ +import Icon from '@components/Icon'; +import styled from '@emotion/styled'; +import { THEME } from '@styles/ThemeProvider/theme'; +import React from 'react'; + +interface AnnounceNotFoundProps { + keyword: string; +} + +const AnnounceNotFound = ({ keyword }: AnnounceNotFoundProps) => { + return ( + + + {`"${keyword}"`}에 관한 공지사항이 없습니다. + + ); +}; + +export default AnnounceNotFound; + +const Container = styled.div` + height: 20rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; +`; + +const Title = styled.span` + color: ${THEME.TEXT.GRAY}; +`; From 47b3c3bbd0f5046f58acd8f7201c393abb1b5bd5 Mon Sep 17 00:00:00 2001 From: hwinkr Date: Fri, 17 Nov 2023 00:16:59 +0900 Subject: [PATCH 31/31] =?UTF-8?q?Refactor:=20=EA=B3=B5=EC=A7=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EA=B2=80=EC=83=89=20=EA=B2=B0=EA=B3=BC=EB=A5=BC=20?= =?UTF-8?q?=ED=8C=90=EB=8B=A8=ED=95=98=EB=8A=94=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/AnnounceSearchList.tsx | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/pages/Announcement/components/AnnounceSearchList.tsx b/src/pages/Announcement/components/AnnounceSearchList.tsx index 26089384..8788bf2c 100644 --- a/src/pages/Announcement/components/AnnounceSearchList.tsx +++ b/src/pages/Announcement/components/AnnounceSearchList.tsx @@ -1,11 +1,10 @@ import AnnounceCard from '@components/Card/AnnounceCard'; -import Icon from '@components/Icon'; -import styled from '@emotion/styled'; -import { THEME } from '@styles/ThemeProvider/theme'; import { AnnounceItem } from '@type/announcement'; import React, { Fragment } from 'react'; import { useLocation } from 'react-router-dom'; +import AnnounceNotFound from './AnnounceNotFound'; + interface AnnounceSearchProps { announceList: AnnounceItem[]; } @@ -17,7 +16,7 @@ const AnnounceSearchList = ({ announceList }: AnnounceSearchProps) => { const searchResult = announceList.filter((announceItem) => announceItem.title.includes(searchKeyword), ); - const hasSearchResult = () => searchResult.length === 0; + const hasSearchResult = () => searchResult.length !== 0; return ( @@ -28,28 +27,10 @@ const AnnounceSearchList = ({ announceList }: AnnounceSearchProps) => { )) ) : ( - - - - {`"${searchKeyword}"`}에 관한 공지사항이 없습니다. - - + )} ); }; export default AnnounceSearchList; - -const AnnounceNotFound = styled.div` - height: 20rem; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 10px; -`; - -const NotFoundTitle = styled.span` - color: ${THEME.TEXT.GRAY}; -`;