diff --git a/public/images/members/152.png b/public/images/members/152.png new file mode 100644 index 00000000..72710449 Binary files /dev/null and b/public/images/members/152.png differ diff --git a/public/images/members/174.png b/public/images/members/174.png new file mode 100644 index 00000000..34f75121 Binary files /dev/null and b/public/images/members/174.png differ diff --git a/public/images/members/209.png b/public/images/members/209.png new file mode 100644 index 00000000..cfe76147 Binary files /dev/null and b/public/images/members/209.png differ diff --git a/public/images/members/246.png b/public/images/members/246.png new file mode 100644 index 00000000..0ae996b7 Binary files /dev/null and b/public/images/members/246.png differ diff --git a/public/images/members/291.png b/public/images/members/291.png new file mode 100644 index 00000000..518cd757 Binary files /dev/null and b/public/images/members/291.png differ diff --git a/public/images/members/354.png b/public/images/members/354.png new file mode 100644 index 00000000..d6312779 Binary files /dev/null and b/public/images/members/354.png differ diff --git a/public/images/members/387.png b/public/images/members/387.png new file mode 100644 index 00000000..66f07452 Binary files /dev/null and b/public/images/members/387.png differ diff --git a/public/images/members/408.png b/public/images/members/408.png new file mode 100644 index 00000000..fe4ab66d Binary files /dev/null and b/public/images/members/408.png differ diff --git a/public/images/members/49.png b/public/images/members/49.png new file mode 100644 index 00000000..05a4929a Binary files /dev/null and b/public/images/members/49.png differ diff --git a/public/images/members/57.png b/public/images/members/57.png new file mode 100644 index 00000000..05a2cb2d Binary files /dev/null and b/public/images/members/57.png differ diff --git a/public/images/members/80.png b/public/images/members/80.png new file mode 100644 index 00000000..f8087529 Binary files /dev/null and b/public/images/members/80.png differ diff --git a/src/assets/icons/ic_github.svg b/src/assets/icons/ic_github.svg new file mode 100644 index 00000000..35fc3351 --- /dev/null +++ b/src/assets/icons/ic_github.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/ic_linkedin.svg b/src/assets/icons/ic_linkedin.svg new file mode 100644 index 00000000..2e36a0f4 --- /dev/null +++ b/src/assets/icons/ic_linkedin.svg @@ -0,0 +1,5 @@ + + + diff --git a/src/assets/icons/ic_school.svg b/src/assets/icons/ic_school.svg new file mode 100644 index 00000000..e0beb67f --- /dev/null +++ b/src/assets/icons/ic_school.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/lib/api/mock/about.ts b/src/lib/api/mock/about.ts index 3f643275..db96e16e 100644 --- a/src/lib/api/mock/about.ts +++ b/src/lib/api/mock/about.ts @@ -51,18 +51,112 @@ const getAboutInfo = async (): Promise => ({ }, }); -const getMemberInfo = async (part?: Part): Promise => ({ - members: Array.from({ length: 12 }, () => - (part ? [part] : [Part.PLAN, Part.ANDROID, Part.DESIGN, Part.IOS, Part.SERVER, Part.WEB]).map( - (part) => ({ - id: Math.floor(Math.random() * 200), - name: '이주함', - description: `2023년 현존하는 최고의 ${part}`, - part, - src: SRC, - }), - ), - ).flat(), +const getMemberInfo = async (): Promise => ({ + members: [ + { + id: 80, + name: '양정윤', + position: '회장', + currentProject: 'palmspring', + description: '알은 세계이다. 태어나려는 자는 세계를 부숴야 한다.', + imageSrc: '/images/members/80.png', + gmail: 'oilburner0320@gmail.com', + }, + { + id: 291, + name: '김대덕', + position: '부회장', + currentProject: 'palmspring', + imageSrc: '/images/members/291.png', + gmail: 'psalm1266@gmail.com', + }, + { + id: 49, + name: '이호재', + position: '총무', + currentProject: 'ZOOC', + description: '함께 성장하는 환경', + imageSrc: '/images/members/49.png', + gmail: 'artjr97@naver.com', + }, + { + id: 246, + name: '김해린', + position: '미디어 팀장', + currentProject: '타투어', + description: '순간의 감정까지 쌓이도록 온 마음을 담아 기록합니다', + imageSrc: '/images/members/246.png', + gmail: 'gogolyn@gmail.com', + linkedin: '해린-김-bb4a8027a', + }, + { + id: 354, + name: '이승준', + position: '운영 팀장', + currentProject: '엄빠도 어렸다', + description: '안녕하세요', + imageSrc: '/images/members/354.png', + gmail: 'tmdwns0527@gmail.com', + }, + { + id: 408, + name: '서지원', + position: '기획 파트장', + currentProject: 'ASAP', + description: '프로덕트 성공에 대한 모든 책임을 질 것', + imageSrc: '/images/members/408.png', + gmail: 'smallbae99@gmail.com', + }, + { + id: 174, + name: '김채현', + position: '디자인 파트장', + currentProject: '타투어', + imageSrc: '/images/members/174.png', + gmail: 'elina001106@gmail.com', + }, + { + id: 57, + name: '이태희', + position: '안드로이드 파트장', + currentProject: 'SPARKLE', + description: '안드로이드 그 자체가 되고 싶은 남자', + imageSrc: '/images/members/57.png', + gmail: 't9h9@naver.com', + github: 'taeheeL', + linkedin: '태희-이-b4988a272', + }, + { + id: 387, + name: '박익범', + position: 'iOS 파트장', + currentProject: 'SPARKLE', + imageSrc: '/images/members/387.png', + gmail: 'pibum@naver.com', + github: 'parkikbum', + }, + { + id: 209, + name: '김서현', + position: '웹 파트장', + currentProject: 'palmspring', + description: '사용자를 생각하는 개발자', + imageSrc: '/images/members/209.png', + gmail: 'seobbangway@ewhain.net', + github: 'seobbang', + linkedin: 'seohyun-kim-9784ab29a', + }, + { + id: 152, + name: '최윤한', + position: '서버 파트장', + currentProject: '스밈, 포포리, 캐쳡', + description: '아슈파', + imageSrc: '/images/members/152.png', + gmail: 'unusualc@likelion.org', + github: 'unanchoi', + }, + ], }); const getStudyInfo = async (): Promise => ({ diff --git a/src/lib/api/remote/about.ts b/src/lib/api/remote/about.ts index 840eb508..3e3833d2 100644 --- a/src/lib/api/remote/about.ts +++ b/src/lib/api/remote/about.ts @@ -4,11 +4,11 @@ import { GetMembersInfoResponse, GetStudyInfoResponse, } from '@src/lib/types/about'; -import { CoreValueResponseDto, MemberResponseDto, StudyResponseDto } from '@src/lib/types/dto'; +import { CoreValueResponseDto, StudyResponseDto } from '@src/lib/types/dto'; import { Part } from '@src/lib/types/universal'; import { parseStringToPart } from '@src/lib/utils/parseStringToPart'; import axios from 'axios'; -import qs from 'qs'; +import { mockAboutAPI } from '../mock/about'; const client = axios.create({ baseURL: BASE_URL, @@ -51,43 +51,8 @@ const getAboutInfo = async (): Promise => { }; }; -const partToFilterParam: Record = { - PLAN: 1, - DESIGN: 2, - WEB: 3, - SERVER: 4, - ANDROID: 5, - iOS: 6, -}; - -const getMemberInfoParams = (part?: Part): { filter?: number; generation: number } => { - const generation = 32; - - if (!part) return { generation }; - - const filter = partToFilterParam[part]; - - return { filter, generation }; -}; - -const getMemberInfo = async (part?: Part): Promise => { - const parameter = qs.stringify(getMemberInfoParams(part)); - - const { - data: { members }, - } = await client.get<{ members: MemberResponseDto[] }>(`/member?${parameter}`); - - return { - members: members - .filter((member) => member.name && member.part) - .map((member) => ({ - id: member.id, - name: member.name, - description: member.introduction, - part: member.part, - src: member.profileImage, - })), - }; +const getMemberInfo = async (): Promise => { + return mockAboutAPI.getMemberInfo(); // todo : implement server connection }; const getStudyInfo = async (): Promise => { diff --git a/src/lib/types/about.ts b/src/lib/types/about.ts index a5b29771..41b07bfd 100644 --- a/src/lib/types/about.ts +++ b/src/lib/types/about.ts @@ -9,11 +9,29 @@ export interface CoreValueType { export interface MemberType { id: number; name: string; + position: PositionType; + currentProject: string; description?: string; - part: string; - src?: string; + imageSrc?: string; + gmail?: string; + linkedin?: string; + github?: string; } +export type PositionType = + | '회장' + | '부회장' + | '총무' + | '미디어 팀장' + | '운영 팀장' + | '기획 파트장' + | '디자인 파트장' + | '안드로이드 파트장' + | 'iOS 파트장' + | '웹 파트장' + | '서버 파트장' + | ''; + export interface AboutInfoType { generation: number; title: string; @@ -56,7 +74,7 @@ export interface GetStudyInfoResponse { export interface AboutAPI { getAboutInfo(): Promise; - getMemberInfo(part?: Part): Promise; + getMemberInfo(): Promise; getStudyInfo(generation?: number): Promise; } diff --git a/src/pages/about.tsx b/src/pages/about.tsx index 7fe4b6f8..872c03b0 100644 --- a/src/pages/about.tsx +++ b/src/pages/about.tsx @@ -22,11 +22,11 @@ const AboutPage = ({ aboutInfo }: InferGetServerSidePropsType + - ); diff --git a/src/views/AboutPage/components/Member/Card/index.tsx b/src/views/AboutPage/components/Member/Card/index.tsx index fb326719..16a5f2bc 100644 --- a/src/views/AboutPage/components/Member/Card/index.tsx +++ b/src/views/AboutPage/components/Member/Card/index.tsx @@ -1,22 +1,59 @@ +import { ReactComponent as IcGithub } from '@src/assets/icons/ic_github.svg'; +import { ReactComponent as IcLinkedin } from '@src/assets/icons/ic_linkedin.svg'; +import { ReactComponent as IcMail } from '@src/assets/icons/mail.svg'; import NullImage from '@src/assets/images/null_image.png'; +import { PositionType } from '@src/lib/types/about'; import * as St from './style'; type MeberCardProps = { - imgSrc?: string; name: string; + position: PositionType; description?: string; - part: string; + currentProject: string; + imageSrc?: string; + gmail?: string; + linkedin?: string; + github?: string; }; -const MemberCard = ({ imgSrc, name, description, part }: MeberCardProps) => { +const MemberCard = ({ + name, + position, + description, + currentProject, + imageSrc, + gmail, + linkedin, + github, +}: MeberCardProps) => { return ( - + - {name} + + {position} + {name} + + {currentProject} {description || '-'} - {part} + + {gmail && ( + + + + )} + {linkedin && ( + + + + )} + {github && ( + + + + )} + ); }; diff --git a/src/views/AboutPage/components/Member/Card/style.ts b/src/views/AboutPage/components/Member/Card/style.ts index 28c7327d..a5b8239d 100644 --- a/src/views/AboutPage/components/Member/Card/style.ts +++ b/src/views/AboutPage/components/Member/Card/style.ts @@ -1,36 +1,29 @@ import styled from '@emotion/styled'; +import { colors } from '@sopt-makers/colors'; import Image from 'next/image'; -import { textSingularLineEllipsis } from '@src/lib/styles/textEllipsis'; +import icSchool from '@src/assets/icons/ic_school.svg'; export const Card = styled.article` display: flex; flex-direction: column; align-items: center; - width: 270px; - height: 400px; + height: 484px; - margin-bottom: 60px; - padding: 38px 49px; + padding: 30px 0; background: #000000; border-radius: 10px; /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - width: 209px; - height: 300px; - - margin-bottom: 40px; - padding: 26px 40px; + @media (max-width: 768px) and (min-width: 428px) { + height: 377px; + padding: 26px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - width: 160px; - height: 265px; - - margin-bottom: 32px; - padding: 18px 17px; + @media (max-width: 427.9px) { + height: 214px; + padding: 12px 0; } `; @@ -48,91 +41,192 @@ export const ImageWrapper = styled.div` overflow: hidden; /* 태블릿, 모바일 뷰 */ - @media (max-width: 1199px) { - width: 126px; - height: 126px; + @media (max-width: 768px) and (min-width: 428px) { + width: 120px; + height: 120px; + } + /* 태블릿, 모바일 뷰 */ + @media (max-width: 427.9px) { + width: 80px; + height: 80px; } `; -export const Name = styled.strong` - ${textSingularLineEllipsis} - width: 100%; - text-align: center; +export const NameWrapper = styled.div` + display: flex; + gap: 4px; + align-items: center; + justify-content: center; + margin-top: 40px; - margin-top: 24px; + /* 태블릿 뷰 */ + @media (max-width: 768px) and (min-width: 428px) { + margin-top: 30px; + gap: 3px; + } + /* 모바일 뷰 */ + @media (max-width: 427.9px) { + margin-top: 18px; + gap: 2px; + } +`; - font-weight: 700; - font-size: 28px; +export const Position = styled.span` + padding: 6px 7px; + color: ${colors.white}; - color: #ffffff; + text-align: center; + font-size: 17px; + font-weight: 600; + line-height: 26px; /* 152.941% */ + letter-spacing: -0.34px; /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - margin-top: 16px; - - font-size: 18px; + @media (max-width: 768px) and (min-width: 428px) { + padding: 4px; + font-size: 12.413px; + line-height: 18.984px; /* 152.941% */ + letter-spacing: -0.248px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - margin-top: 16px; - - font-size: 16px; + @media (max-width: 427.9px) { + padding: 3px; + font-size: 7.535px; + line-height: 11.524px; /* 152.941% */ + letter-spacing: -0.151px; } `; -export const Desc = styled.p` - ${textSingularLineEllipsis} - width: 100%; - height: 26px; +export const Name = styled.strong` text-align: center; + font-size: 28px; - margin-top: 8px; - font-size: 18px; - line-height: 26px; + color: ${colors.white}; + font-weight: 600; + line-height: 100%; /* 28px */ + letter-spacing: -0.28px; - color: rgba(255, 255, 255, 0.5); + /* 태블릿 뷰 */ + @media (max-width: 768px) and (min-width: 428px) { + font-size: 18px; + } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - margin-top: 4px; + @media (max-width: 427.9px) { font-size: 16px; } `; -export const Part = styled.div` - ${textSingularLineEllipsis} - max-width: 100%; - - display: flex; - justify-content: center; - align-items: center; +export const Desc = styled.span` + text-align: center; - margin-top: 12px; + margin-top: 15px; + font-size: 15px; + font-style: normal; + line-height: 26px; /* 173.333% */ + letter-spacing: -0.3px; + color: ${colors.white}; + background-color: #21212c; padding: 10px 16px; + border-radius: 10px; + /* 태블릿 뷰 */ + @media (max-width: 768px) and (min-width: 428px) { + font-size: 10.952px; + font-style: normal; + font-weight: 400; + line-height: 18.984px; /* 173.333% */ + letter-spacing: -0.219px; + padding: 7px 12px; + border-radius: 8px; + } + /* 모바일 뷰 */ + @media (max-width: 427.9px) { + font-size: 6.648px; + font-style: normal; + font-weight: 400; + line-height: 11.524px; /* 173.333% */ + letter-spacing: -0.133px; + padding: 4px 7px; + border-radius: 4px; + } +`; - background: #333333; - border-radius: 30px; - - font-size: 18px; - line-height: 26px; +export const CurrentProject = styled.span` + position: relative; + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + background-image: url(${icSchool}); + background-repeat: no-repeat; + background-size: contain; + width: 24px; + height: 24px; + /* 태블릿 뷰 */ + @media (max-width: 768px) and (min-width: 428px) { + width: 18px; + height: 18px; + } + /* 모바일 뷰 */ + @media (max-width: 427.9px) { + width: 12px; + height: 12px; + } + } - color: #ffffff; + height: 24px; + padding-left: 28px; + color: #bcbcbc; + font-size: 15px; + font-style: normal; + font-weight: 400; + line-height: 26px; /* 173.333% */ + letter-spacing: -0.3px; + margin-top: 16px; /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { + @media (max-width: 768px) and (min-width: 428px) { + height: 18px; + padding-left: 20px; + font-size: 10.952px; + font-style: normal; + font-weight: 400; + line-height: 18.984px; /* 173.333% */ + letter-spacing: -0.219px; + margin-top: 12px; + } + /* 모바일 뷰 */ + @media (max-width: 427.9px) { + height: 12px; + padding-left: 13px; + font-size: 6.648px; + font-weight: 400; + line-height: 11.524px; /* 173.333% */ + letter-spacing: -0.133px; margin-top: 8px; - padding: 10px 16px; - - background: #333333; - border-radius: 30px; + } +`; - font-size: 18px; - line-height: 26px; +export const LinkWrapper = styled.div` + display: flex; + justify-content: center; + align-items: flex-end; + gap: 16px; + flex: 1; + height: 100%; + /* 태블릿 뷰 */ + @media (max-width: 768px) and (min-width: 428px) { + gap: 12px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - margin-top: 6px; + @media (max-width: 427.9px) { + gap: 0; + } +`; - font-size: 12px; - line-height: 15px; +export const AnchorIconWrapper = styled.a` + /* 모바일 뷰 */ + @media (max-width: 427.9px) { + transform: scale(0.7); } `; diff --git a/src/views/AboutPage/components/Member/Content/index.tsx b/src/views/AboutPage/components/Member/Content/index.tsx index 0ec418c9..7dabb01d 100644 --- a/src/views/AboutPage/components/Member/Content/index.tsx +++ b/src/views/AboutPage/components/Member/Content/index.tsx @@ -1,53 +1,59 @@ -import { track } from '@amplitude/analytics-browser'; -import { useMemo, useState } from 'react'; +import { useMemo } from 'react'; import DataErrorBanner from '@src/components/DataErrorBanner'; import Flex from '@src/components/common/Flex'; -import { ExtraPart, ExtraTabType } from '@src/lib/types/universal'; -import { PartExtraType } from '@src/lib/types/universal'; import { emptyMembers } from '@src/views/AboutPage/constant/emptyMembers'; import useFetchMember from '@src/views/AboutPage/hooks/useFetchMemeber'; -import useResponsiveMember from '@src/views/AboutPage/hooks/useResponsiveMember'; import { OvalSpinner } from '@src/views/ProjectPage/components'; -import TabBar from '../../common/TabBar'; import MemberCard from '../Card'; import * as St from './style'; const MemberContent = () => { - const { memberCardsCount, shouldNotShownWithError } = useResponsiveMember(); - - const [currentPart, setCurrentPart] = useState(PartExtraType.ALL); - const state = useFetchMember(currentPart); + const state = useFetchMember(); const errorContent = state._TAG === 'ERROR' && ; - const handleTabClick = (tab: ExtraTabType) => { - setCurrentPart(tab.value); - track('click_about_member_part', { part: tab.label }); - }; - const tabBarContent = !(state._TAG === 'ERROR' && shouldNotShownWithError) && ( - - ); - const cardContent = useMemo(() => { - if (state._TAG === 'OK') - return state.data.members.map(({ id, name, src, description, part }) => ( - - )); - if (state._TAG === 'ERROR') - return emptyMembers(memberCardsCount).map(({ id, name, src, description, part }) => ( - - )); + const cardContent = useMemo(() => { + if (state._TAG === 'OK' || state._TAG === 'ERROR') + return (state._TAG === 'OK' ? state.data.members : emptyMembers(6)).map( + ({ + id, + name, + position, + description, + currentProject, + imageSrc, + gmail, + linkedin, + github, + }) => ( + + ), + ); return ( ); - }, [state, memberCardsCount]); + }, [state]); return ( - + {errorContent} - {tabBarContent} {cardContent} ); diff --git a/src/views/AboutPage/components/Member/Content/style.ts b/src/views/AboutPage/components/Member/Content/style.ts index 0983407e..2230df1d 100644 --- a/src/views/AboutPage/components/Member/Content/style.ts +++ b/src/views/AboutPage/components/Member/Content/style.ts @@ -1,16 +1,31 @@ import styled from '@emotion/styled'; export const CardContainer = styled.div` - display: flex; - flex-wrap: wrap; - gap: 30px; - /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - gap: 20px; + display: grid; + + grid-template-columns: repeat(3, 1fr); + gap: 34px; + width: 1200px; + + @media (max-width: 1280px) and (min-width: 1170px) { + width: calc(100% - 40px); + } + + @media (max-width: 1170px) and (min-width: 768px) { + grid-template-columns: repeat(2, 1fr); + width: 752px; + } + + @media (max-width: 768px) and (min-width: 584px) { + grid-template-columns: repeat(2, 1fr); + gap: 24px; + width: 576px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - gap: 10px; + @media (max-width: 584px) { + grid-template-columns: repeat(2, 1fr); + gap: 15px; + width: max(350px, 100% - 40px); } `; diff --git a/src/views/AboutPage/components/Member/Section/index.tsx b/src/views/AboutPage/components/Member/Section/index.tsx index 14301579..0129e631 100644 --- a/src/views/AboutPage/components/Member/Section/index.tsx +++ b/src/views/AboutPage/components/Member/Section/index.tsx @@ -1,7 +1,7 @@ -import styled from '@emotion/styled'; import Flex from '@src/components/common/Flex'; -import SectionTitle from '../../common/SectionTitle'; +import SectionTop from '../../common/SectionTop'; import MemberContent from '../Content'; +import * as St from './style'; type MemberSectionProps = { generation: number; @@ -14,22 +14,16 @@ const MemberSection = ({ generation }: MemberSectionProps) => { gap={{ mobile: 24, tablet: 48, desktop: 60 }} style={{ position: 'relative' }} > - {/* member 2뎁스 탭 개발 이 삭제 필요 */} - - {generation - 1}기 활동 멤버들 + + + {/* TODO : 서버에서 description을 받아오도록 수정 */} ); }; -const ScrollGhost = styled.div` - position: absolute; - top: -100px; - - /* 모바일 뷰 */ - @media (max-width: 765.9px) { - top: -60px; - } -`; - export default MemberSection; diff --git a/src/views/AboutPage/components/Member/Section/style.ts b/src/views/AboutPage/components/Member/Section/style.ts new file mode 100644 index 00000000..e7333aa6 --- /dev/null +++ b/src/views/AboutPage/components/Member/Section/style.ts @@ -0,0 +1,12 @@ +import styled from '@emotion/styled'; + +export const MarginTop = styled.div` + height: 275px; + @media (max-width: 1440px) and (min-width: 766px) { + height: 190px; + } + /* 모바일 뷰 */ + @media (max-width: 765.9px) { + height: 120px; + } +`; diff --git a/src/views/AboutPage/components/Record/Item/index.tsx b/src/views/AboutPage/components/Record/Item/index.tsx index 82ff5aa3..d79a77b3 100644 --- a/src/views/AboutPage/components/Record/Item/index.tsx +++ b/src/views/AboutPage/components/Record/Item/index.tsx @@ -1,24 +1,43 @@ import { track } from '@amplitude/analytics-browser'; +import { PropsWithChildren } from 'react'; import Flex from '@src/components/common/Flex'; import NumberRoller from '@src/components/common/NumberRoller'; import { RECORD_TITLE } from '@src/lib/constants/about'; import { RecordTitle } from '@src/lib/types/about'; import * as St from './style'; -type RecordItemProps = { - href: string; - title: RecordTitle; - countNumber?: number; - countString?: string; -}; +type RecordItemProps = + | { + type: 'link'; + href: string; + title: RecordTitle; + countNumber?: number; + countString?: string; + } + | { + type: 'block'; + title: RecordTitle; + countNumber?: number; + countString?: string; + }; -const RecordItem = (props: RecordItemProps) => { +const RecordItemWrapper = (props: PropsWithChildren) => { const trackRecordClick = () => { track(`click_about_${RECORD_TITLE[props.title]}`); }; + if (props.type == 'link') + return ( + + {props.children} + + ); + return {props.children}; +}; + +const RecordItem = (props: RecordItemProps) => { return ( - + { {props.countString && {props.countString}} - + ); }; diff --git a/src/views/AboutPage/components/Record/Item/style.ts b/src/views/AboutPage/components/Record/Item/style.ts index 450158aa..71c42977 100644 --- a/src/views/AboutPage/components/Record/Item/style.ts +++ b/src/views/AboutPage/components/Record/Item/style.ts @@ -1,34 +1,54 @@ import styled from '@emotion/styled'; import Link from 'next/link'; -import arrowRight from '@src/assets/icons/arrow_right_16x16.svg'; +import { css } from '@emotion/react'; -export const LinkWrapper = styled(Link)` - width: 100%; - background-color: #000000; - border-radius: 10px; +const wrapperStyle = css` + width: 380px; height: 280px; + background-color: #141518; + border-radius: 10px; + + @media (max-width: 996px) and (min-width: 766px) { + width: 285px; + height: 210px; + } + /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - height: 180px; + @media (max-width: 766px) and (min-width: 428px) { + width: 204px; + height: 150px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - height: 120px; + @media (max-width: 428px) { + width: 204px; + height: 150px; } `; +export const LinkWrapper = styled(Link)` + ${wrapperStyle} +`; + +export const BlockWrapper = styled.div` + ${wrapperStyle} +`; + export const Title = styled.div` font-size: 20px; letter-spacing: -1%; color: white; + @media (max-width: 996px) and (min-width: 766px) { + font-size: 16px; + } + /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - font-size: 18px; + @media (max-width: 766px) and (min-width: 428px) { + font-size: 10px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - font-size: 12px; + @media (max-width: 428px) { + font-size: 10px; } `; @@ -38,39 +58,19 @@ export const Count = styled.div` font-size: 45px; color: white; line-height: 60px; + + @media (max-width: 996px) and (min-width: 766px) { + font-size: 38px; + line-height: 48px; + } /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - font-size: 28px; - line-height: 40px; + @media (max-width: 766px) and (min-width: 428px) { + font-size: 24px; + line-height: 32px; } /* 모바일 뷰 */ - @media (max-width: 765.9px) { - font-size: 18px; - line-height: 18px; - } - - &::after { - position: absolute; - content: ''; - mask-image: url(${arrowRight}); - mask-repeat: no-repeat; - mask-size: cover; - background-color: #787878; - width: 32px; - height: 40px; - margin-top: 9px; - - /* 태블릿 뷰 */ - @media (max-width: 1199px) and (min-width: 766px) { - width: 16px; - height: 20px; - margin-top: 9px; - } - /* 모바일 뷰 */ - @media (max-width: 765.9px) { - width: 12px; - height: 15px; - margin-top: 1px; - } + @media (max-width: 428px) { + font-size: 14px; + line-height: 32px; } `; diff --git a/src/views/AboutPage/components/Record/List/index.tsx b/src/views/AboutPage/components/Record/List/index.tsx index 14963e4c..556a33fe 100644 --- a/src/views/AboutPage/components/Record/List/index.tsx +++ b/src/views/AboutPage/components/Record/List/index.tsx @@ -1,31 +1,32 @@ -import Flex from '@src/components/common/Flex'; import { AboutInfoType } from '@src/lib/types/about'; import RecordItem from '../Item'; +import * as St from './style'; type RecordListProps = Pick; const RecordList = (props: RecordListProps) => { return ( - + - + ); }; diff --git a/src/views/AboutPage/components/Record/List/style.ts b/src/views/AboutPage/components/Record/List/style.ts new file mode 100644 index 00000000..5fcebe4a --- /dev/null +++ b/src/views/AboutPage/components/Record/List/style.ts @@ -0,0 +1,27 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.div` + display: flex; + gap: 30px; + justify-content: center; + align-items: center; + padding: 0 20px; + + @media (max-width: 996px) and (min-width: 766px) { + gap: 24px; + } + + @media (max-width: 766px) and (min-width: 428px) { + gap: 20px; + } + + @media (max-width: 520px) { + flex-direction: column; + } + + /* 모바일 뷰 */ + @media (max-width: 428px) { + flex-direction: column; + gap: 16px; + } +`; diff --git a/src/views/AboutPage/components/Record/Section/index.tsx b/src/views/AboutPage/components/Record/Section/index.tsx index 46f4565d..6919cb59 100644 --- a/src/views/AboutPage/components/Record/Section/index.tsx +++ b/src/views/AboutPage/components/Record/Section/index.tsx @@ -1,16 +1,16 @@ -import Flex from '@src/components/common/Flex'; import { AboutInfoType } from '@src/lib/types/about'; -import SectionTitle from '../../common/SectionTitle'; +import SectionTop from '../../common/SectionTop'; import RecordList from '../List'; +import * as St from './style'; type RecordSectionProps = Pick; const RecordSection = (props: RecordSectionProps) => { return ( - - {props.generation - 1}기 활동 레코드 + + - + ); }; diff --git a/src/views/AboutPage/components/Record/Section/style.ts b/src/views/AboutPage/components/Record/Section/style.ts new file mode 100644 index 00000000..82893127 --- /dev/null +++ b/src/views/AboutPage/components/Record/Section/style.ts @@ -0,0 +1,22 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.section` + margin-top: 275px; + margin-bottom: 340px; + gap: 48px; + display: flex; + flex-direction: column; + + @media (max-width: 766px) and (min-width: 428px) { + margin-top: 190px; + margin-bottom: 218px; + gap: 28px; + } + + /* 모바일 뷰 */ + @media (max-width: 428px) { + margin-top: 120px; + margin-bottom: 136px; + gap: 26px; + } +`; diff --git a/src/views/AboutPage/constant/emptyMembers.ts b/src/views/AboutPage/constant/emptyMembers.ts index 407f9c3a..caa2bda4 100644 --- a/src/views/AboutPage/constant/emptyMembers.ts +++ b/src/views/AboutPage/constant/emptyMembers.ts @@ -5,8 +5,10 @@ export const emptyMembers = (count: number): MemberType[] => { return Array.from({ length: count }).map((_, idx) => ({ id: idx, name: '-', + position: '', + currentProject: '', description: '-', part: '-', - src: NullImage.src, + imageSrc: NullImage.src, })); }; diff --git a/src/views/AboutPage/hooks/useFetchMemeber.ts b/src/views/AboutPage/hooks/useFetchMemeber.ts index c78b6697..07d270f6 100644 --- a/src/views/AboutPage/hooks/useFetchMemeber.ts +++ b/src/views/AboutPage/hooks/useFetchMemeber.ts @@ -1,15 +1,12 @@ import { useCallback } from 'react'; import useFetchBase from '@src/hooks/useFetchBase'; import { api } from '@src/lib/api'; -import { ExtraPart, PartExtraType } from '@src/lib/types/universal'; -const useFetchMember = (part: ExtraPart) => { +const useFetchMember = () => { const willFetch = useCallback(async () => { - const response = await api.aboutAPI.getMemberInfo( - part === PartExtraType.ALL ? undefined : part, - ); + const response = await api.aboutAPI.getMemberInfo(); return response; - }, [part]); + }, []); const state = useFetchBase(willFetch); return state; }; diff --git a/src/views/AboutPage/hooks/useResponsiveMember.ts b/src/views/AboutPage/hooks/useResponsiveMember.ts deleted file mode 100644 index 5effc229..00000000 --- a/src/views/AboutPage/hooks/useResponsiveMember.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { useMemo } from 'react'; -import { useIsMobile, useIsTablet } from '@src/hooks/useDevice'; - -const useResponsiveMember = () => { - const isTablet = useIsTablet('766px', '1199.9px'); - const isMobile = useIsMobile(); - - const memberCardsCount = useMemo(() => { - if (isMobile) return 2; - if (isTablet) return 3; - return 4; - }, [isMobile, isTablet]); - - return { memberCardsCount, shouldNotShownWithError: isMobile }; -}; - -export default useResponsiveMember;