Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor/#289: 공지사항, FAQ 페이지에 UpperLayout 합성 컴포넌트 적용 & 팁 페이지 이미지 수정 #292

Merged
merged 19 commits into from
Dec 3, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
80910bf
chore(delete unused component): 사용하지 않는 컴포넌트 삭제
hwinkr Nov 30, 2023
4059469
chore(modify image demension): 팁 페이지에서 사용할 백경이 png 이미지 변경
hwinkr Dec 1, 2023
888288f
chore(modify image demension): 팁 페이지에서 사용할 백경이 webp 이미지 변경
hwinkr Dec 1, 2023
d81b08c
chore(add icon): 아래방향 화살표, 학교 빌딩 아이콘 추가
hwinkr Dec 1, 2023
69de644
refactor(modify icon type): 컴포넌트에서 사용되는 아이콘 타입 변경
hwinkr Dec 1, 2023
de84e25
refactor(edit test code): 컴포넌트에서 사용하는 아이콘이 변경되어, 테스트 코드 수정
hwinkr Dec 1, 2023
53688cc
refactor(modify icon animation): 사용자가 FAQ를 클릭할 경우 적용됐던 화살표 아이콘 애니메이션 …
hwinkr Dec 1, 2023
1f6530b
feat(add InformSearchForm): 합성 컴포넌트 구성에 InformSearchForm 컴포넌트 추가
hwinkr Dec 1, 2023
dd24137
feat(InformSearchForm): 정보를 검색할 수 있는 검색바 컴포넌트 구현
hwinkr Dec 1, 2023
4c454ef
refactor(add InformSearchForm): children 컴포넌트들의 타입을 확인하는 함수에 검색 바 컴포넌…
hwinkr Dec 1, 2023
3ac931f
refactor(remove boundaryLine): 공지사항 리스트 컴포넌트에서 BoundaryLine 컴포넌트 삭제
hwinkr Dec 1, 2023
5f90f7e
chore(modify image import path): 팁 페이지에서 사용할 이미지 import 경로 수정
hwinkr Dec 1, 2023
5289959
refactor(use compound component): 공지사항 컨테이너 컴포넌트에서 상단 레이아웃 합성 컴포넌트를 적용
hwinkr Dec 1, 2023
4a4b806
chore(delete unused component): 사용하지 않는 컴포넌트 export 경로에서 제거
hwinkr Dec 1, 2023
a1cce3d
chore(edit usage icon): 학교, 학과 공지사항 카드 컴포넌트에서 사용되는 아이콘 구분
hwinkr Dec 1, 2023
4f6c3b0
refactor(use compound component): FAQ 페이지에 상단 레이아웃 합성 컴포넌트 적용
hwinkr Dec 1, 2023
8886947
chore(delete unused css code): 적용되지 않는 css 코드 제거
hwinkr Dec 1, 2023
174ec9b
chore(delete unused module): 사용하지 않는 모듈 제거
hwinkr Dec 1, 2023
33e7ab0
chore(modify css code): 불필요한 margin 제거
hwinkr Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified public/assets/tipImages/png/baekgyeong_camera.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/assets/tipImages/png/baekgyeong_hi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/assets/tipImages/png/baekgyeong_love.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/assets/tipImages/png/baekgyeong_search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/assets/tipImages/png/baekgyeong_teach.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/assets/tipImages/png/pknu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/assets/tipImages/webp/baekgyeong_camera.webp
Binary file not shown.
Binary file not shown.
Binary file modified public/assets/tipImages/webp/baekgyeong_hi.webp
Binary file not shown.
Binary file modified public/assets/tipImages/webp/baekgyeong_love.webp
Binary file not shown.
Binary file modified public/assets/tipImages/webp/baekgyeong_search.webp
Binary file not shown.
Binary file modified public/assets/tipImages/webp/baekgyeong_teach.webp
Binary file not shown.
Binary file modified public/assets/tipImages/webp/pknu.webp
Binary file not shown.
4 changes: 3 additions & 1 deletion src/@types/styles/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ export type IconKind =
| 'menu'
| 'notification'
| 'school'
| 'arrowBack'
| 'schoolBuilding'
| 'arrowRight'
| 'arrowDown'
| 'arrowBack'
| 'plus'
| 'edit'
| 'suggest'
Expand Down
6 changes: 3 additions & 3 deletions src/components/Card/InformCard/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ type INFORM_CARD_TYPE = 'ANNOUNCEMENT' | 'GRADUATION';
type INFORM_CARD_DATA = {
[key in INFORM_CARD_TYPE]: {
title: string;
icon: IconKind & ('school' | 'notification');
icon: IconKind & ('school' | 'schoolBuilding');
onClick: () => void;
};
};

const graduationLink = 'https://ce.pknu.ac.kr/ce/2889';
const INFORM_CARD: INFORM_CARD_DATA = {
ANNOUNCEMENT: {
title: '공지사항',
icon: 'notification',
title: '학교 공지사항',
icon: 'schoolBuilding',
onClick: () => mockRouterTo('/announcement'),
},
GRADUATION: {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Card/InformCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { THEME } from '@styles/ThemeProvider/theme';
import { IconKind } from '@type/styles/icon';

interface InformCardProps {
icon: IconKind & ('school' | 'notification');
icon: IconKind & ('school' | 'schoolBuilding' | 'speaker');
title: string;
majorRequired: boolean;
onClick: () => void;
Expand Down
6 changes: 5 additions & 1 deletion src/components/Common/Icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
MdHome,
MdAccountCircle,
MdSchool,
MdOutlineLocationCity,
MdNotifications,
MdMenu,
MdArrowBackIos,
Expand All @@ -26,6 +27,7 @@ import {
MdOutlineMyLocation,
MdOutlineError,
MdOutlineKeyboardArrowRight,
MdOutlineKeyboardArrowDown,
} from 'react-icons/md';

const ICON: { [key in IconKind]: IconType } = {
Expand All @@ -35,8 +37,10 @@ const ICON: { [key in IconKind]: IconType } = {
menu: MdMenu,
notification: MdNotifications,
school: MdSchool,
arrowBack: MdArrowBackIos,
schoolBuilding: MdOutlineLocationCity,
arrowRight: MdOutlineKeyboardArrowRight,
arrowDown: MdOutlineKeyboardArrowDown,
arrowBack: MdArrowBackIos,
plus: MdAddCircleOutline,
edit: MdOutlineModeEdit,
suggest: MdOutlineQuestionAnswer,
Expand Down
18 changes: 9 additions & 9 deletions src/components/FAQBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,22 @@ const FAQBox = ({ question, answer }: FAQBoxProps) => {
const [showAnswer, setShowAnswer] = useState<boolean>(false);
const toggleAnswer = () => setShowAnswer((prevState) => !prevState);

const answerTextSeperatedLine = answer.text.split(
FAQ_CONSTANTS.LINE_SEPERATOR,
);
const moveToLink = () => {
if (!answer.link) return;
openLink(answer.link);
};

const hasAnswerLink = () => !!answer.link;
const answerTextSeperatedLine = answer.text.split(
FAQ_CONSTANTS.LINE_SEPERATOR,
);

return (
<>
<QuestionContainer onClick={toggleAnswer} showAnswer={showAnswer}>
<QuestionMark>{FAQ_CONSTANTS.QUESTION_MARK}</QuestionMark>
<QuestionText>{question}</QuestionText>
<IconContainer>
<Icon kind="arrowRight" size="24" />
<Icon kind="arrowDown" size="24" />
</IconContainer>
</QuestionContainer>
{showAnswer && (
Expand All @@ -47,7 +46,6 @@ const FAQBox = ({ question, answer }: FAQBoxProps) => {
)}
</AnswerContainer>
)}

<BoundaryLine />
</>
);
Expand All @@ -66,7 +64,7 @@ const QuestionContainer = styled.div<{ showAnswer: boolean }>`
color: ${showAnswer && THEME.PRIMARY};
}
& > div > svg {
transform: ${showAnswer ? 'rotate(90deg)' : 'rotate(0deg)'};
transform: ${showAnswer ? 'rotate(-180deg)' : 'rotate(0deg)'};
transition: all ease 0.3s;
}
`}
Expand Down Expand Up @@ -102,6 +100,8 @@ const StyledLink = styled.span`
border-bottom: 1px solid ${THEME.PRIMARY};
`;

const BoundaryLine = styled.div`
border-bottom: 1px solid #ededed;
const BoundaryLine = styled.hr`
height: 1px;
background-color: #ededed;
border: none;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ import useRouter from '@hooks/useRouter';
import useToasts from '@hooks/useToast';
import React, { useRef } from 'react';

interface AnnounceSearchProps {
interface InformSearchForm {
category: 'school' | 'major';
}

const AnnounceSearch = ({ category }: AnnounceSearchProps) => {
const InformSearchForm = ({ category }: InformSearchForm) => {
const { routerTo } = useRouter();
const { addToast } = useToasts();

const inputRef = useRef<HTMLInputElement>(null);

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
if (!inputRef.current) return;
e.preventDefault();

if (inputRef.current.value.length === 0) {
addToast(TOAST_MESSAGES.SEARCH_KEYWORD);
return;
Expand All @@ -31,22 +31,20 @@ const AnnounceSearch = ({ category }: AnnounceSearchProps) => {
};

return (
<div>
<StyledForm onSubmit={handleSubmit}>
<StyledInput
ref={inputRef}
type="text"
placeholder={PLCACEHOLDER_MESSAGES.SEARCH_TITLE}
/>
<StyledIconWrapper onClick={() => handleSubmit}>
<Icon kind="search" color="#7A9DD3" />
</StyledIconWrapper>
</StyledForm>
</div>
<StyledForm onSubmit={handleSubmit}>
<StyledInput
ref={inputRef}
type="text"
placeholder={PLCACEHOLDER_MESSAGES.SEARCH_TITLE}
/>
<StyledIconWrapper onClick={() => handleSubmit}>
<Icon kind="search" color="#7A9DD3" />
</StyledIconWrapper>
</StyledForm>
);
};

export default AnnounceSearch;
export default InformSearchForm;

const StyledForm = styled.form`
display: flex;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Children, isValidElement } from 'react';

import InformSearchForm from '../InformSearchForm';
import InformSubTitle from '../InformSubTitle';
import InformTitle from '../InformTitle';
import InformTypeButton from '../InformTypeButton';

type InformUpperLayoutChildType =
| typeof InformTitle
| typeof InformSubTitle
| typeof InformTypeButton;
| typeof InformTypeButton
| typeof InformSearchForm;

const getInformUpperLayoutSubElement = (
children: React.ReactNode,
Expand Down
9 changes: 8 additions & 1 deletion src/components/InformUpperLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import styled from '@emotion/styled';
import React from 'react';

import getInformUpperLayoutSubElement from './domain/getInformUpperLayoutSubElement';
import InformSearchForm from './InformSearchForm';
import InformSubTitle from './InformSubTitle';
import InformTitle from './InformTitle';
import InformTypeButton from './InformTypeButton';
Expand All @@ -18,11 +19,16 @@ const InformUpperLayout = ({ children }: StrictPropsWithChildren) => {
children,
InformTypeButton,
);
const informSearchForm = getInformUpperLayoutSubElement(
children,
InformSearchForm,
);

return (
<Container>
{informTitle}
{informSubTitle}
{informSearchForm}
{informTypeButton && (
<TypeButtonContainer>{informTypeButton}</TypeButtonContainer>
)}
Expand All @@ -35,6 +41,7 @@ export default InformUpperLayout;
InformUpperLayout.InformTitle = InformTitle;
InformUpperLayout.InformSubTitle = InformSubTitle;
InformUpperLayout.InformTypeButton = InformTypeButton;
InformUpperLayout.InformSearchForm = InformSearchForm;

const Container = styled.section`
padding: 0px 20px 0px 20px;
Expand All @@ -43,7 +50,7 @@ const Container = styled.section`
`;

const TypeButtonContainer = styled.div`
padding: 0 0 10px 0;
padding: 10px 0 10px 0;
display: flex;
column-gap: 10px;
`;
5 changes: 0 additions & 5 deletions src/components/List/AnnounceList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const AnnounceList = ({ resource, type }: AnnounceListProps) => {

return (
<>
<BoundaryLine />
{type === ANNOUNCEMENT_TYPE.NORMAL &&
normalAnnouncemnet.map((announce, idx) => (
<Fragment key={idx}>
Expand All @@ -55,7 +54,3 @@ const AnnounceList = ({ resource, type }: AnnounceListProps) => {
};

export default AnnounceList;

const BoundaryLine = styled.div`
border-bottom: 1px solid ${THEME.TEXT.BLACK};
`;
4 changes: 2 additions & 2 deletions src/constants/tip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export const SHORTCUT_DATA: readonly TipData[] = [
{
title: '이루미',
subTitle: '부경대 포털 사이트\n바로가기',
webpPath: '/assets/tipImages/webp/baekgyeong_teach.webp',
pngPath: '/assets/tipImages/png/baekgyeong_teach.png',
webpPath: '/assets/tipImages/webp/baekgyeong_hand_love.webp',
pngPath: '/assets/tipImages/png/baekgyeong_hand_love.png',
link: 'https://portal.pknu.ac.kr/',
},
{
Expand Down
49 changes: 22 additions & 27 deletions src/pages/Announcement/components/AnnounceContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import fetchAnnounceList from '@apis/Suspense/fetch-announce-list';
import InformUpperLayout from '@components/InformUpperLayout';
import AnnounceList from '@components/List/AnnounceList';
import AnnounceCardSkeleton from '@components/List/AnnounceList/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 { THEME } from '@styles/ThemeProvider/theme';
import {
AnnounceItemList,
AnnouncementCategory,
Expand All @@ -14,9 +16,6 @@ import {
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;
Expand Down Expand Up @@ -45,20 +44,21 @@ const AnnounceContainer = ({

return (
<Container>
<AnnounceTitle>{title}</AnnounceTitle>
<AnnounceSearch category={category} />
<ButtonContainer>
<AnnounceTypeButtons
<InformUpperLayout>
<InformUpperLayout.InformTitle title={title} />
<InformUpperLayout.InformSearchForm category={category} />
<InformUpperLayout.InformTypeButton
type="일반"
onClick={showNormalAnnouncement}
isActive={type === ANNOUNCEMENT_TYPE.NORMAL}
onClick={showNormalAnnouncement}
/>
<AnnounceTypeButtons
<InformUpperLayout.InformTypeButton
type="고정"
onClick={showPinnedAnnouncement}
isActive={type === ANNOUNCEMENT_TYPE.PINNED}
onClick={showPinnedAnnouncement}
/>
</ButtonContainer>
</InformUpperLayout>
<BoundaryLine />
<AnnounceListContainer type={type as AnnouncementType}>
<Suspense fallback={<AnnounceCardSkeleton length={30} />}>
<AnnounceList resource={resource} type={type as AnnouncementType} />
Expand All @@ -71,23 +71,9 @@ const AnnounceContainer = ({
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;
overflow-x: hidden;
`;

const getAnimationType = (type: AnnouncementType) => {
Expand All @@ -96,7 +82,8 @@ const getAnimationType = (type: AnnouncementType) => {
};

const AnnounceListContainer = styled.div<{ type: AnnouncementType }>`
width: 100%;
padding: 0 20px 0 20px;

overflow: hidden;
animation: ${({ type }) => getAnimationType(type)} 0.3s forwards;
`;
Expand All @@ -118,3 +105,11 @@ const AnnounceSlideLeft = keyframes`
transform: translateX(0%);
}
`;

const BoundaryLine = styled.hr`
height: 1px;
width: calc(100% - 40px);
margin: 0 auto;
background-color: ${THEME.TEXT.BLACK};
border: none;
`;
Loading