Skip to content

Commit

Permalink
Merge branch 'develop' into feat/#290-main-part-config
Browse files Browse the repository at this point in the history
  • Loading branch information
solar3070 committed Dec 10, 2023
2 parents 2b8b5b0 + 3792f7e commit 5d26f80
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 1 deletion.
Binary file added src/assets/images/img_main_makers_card.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 added src/assets/images/img_main_mind_card.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions src/components/common/FlippableCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import useBooleanState from '@src/hooks/useBooleanState';
import { useDeviceType } from '@src/hooks/useDevice';
import * as S from './style';

type FlippableCardProps = {
frontContent: React.ReactNode;
backContent: React.ReactNode;
};

const useFlippableCard = () => {
const [isFlipped, setIsFlipped, setIsUnflipped, toggleFlipped] = useBooleanState(false);
const deviceType = useDeviceType();

if (deviceType === 'desktop') {
return { isFlipped, onMouseEnter: setIsFlipped, onMouseLeave: setIsUnflipped };
}
return { isFlipped, onClick: toggleFlipped };
};

export default function FlippableCard({ frontContent, backContent }: FlippableCardProps) {
const { isFlipped, ...eventListeners } = useFlippableCard();

const variants = {
front: { rotateY: 0 },
back: { rotateY: 180 },
};

return (
<div {...eventListeners}>
<S.CardWrapper
animate={isFlipped ? 'back' : 'front'}
variants={variants}
transition={{ duration: 0.2 }}
>
<S.FrontSideCardWrapper>{frontContent}</S.FrontSideCardWrapper>
<S.BackSideCardWrapper>{backContent}</S.BackSideCardWrapper>
</S.CardWrapper>
</div>
);
}
20 changes: 20 additions & 0 deletions src/components/common/FlippableCard/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import styled from '@emotion/styled';
import { motion } from 'framer-motion';

export const CardWrapper = styled(motion.div)`
transition: 0.2s;
display: inline-grid;
transform: perspective(800px) rotateY(0deg);
transform-style: preserve-3d;
`;

export const SideCardWrapper = styled.div`
grid-area: 1 / 1 / 1 / 1;
backface-visibility: hidden;
`;

export const FrontSideCardWrapper = styled(SideCardWrapper)``;

export const BackSideCardWrapper = styled(SideCardWrapper)`
transform: rotateY(180deg);
`;
55 changes: 54 additions & 1 deletion src/lib/constants/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { default as ImgEvent } from '@src/assets/images/img_event.jpg';
import { default as ImgIntroCard1 } from '@src/assets/images/img_intro_card1.png';
import { default as ImgIntroCard2 } from '@src/assets/images/img_intro_card2.png';
import { default as ImgIntroCard3 } from '@src/assets/images/img_intro_card3.png';
import { default as ImgMakersCard } from '@src/assets/images/img_main_makers_card.png';
import { default as ImgMindCard } from '@src/assets/images/img_main_mind_card.png';
import { default as ImgSeminar } from '@src/assets/images/img_seminar.jpg';
import { default as ImgSoptkaton } from '@src/assets/images/img_soptkaton.jpg';
import { default as ImgSoptterm } from '@src/assets/images/img_soptterm.jpg';
import { default as ImgStudy } from '@src/assets/images/img_study.jpg';
import { ActivityType, KeywordListType, PartListType } from '@src/lib/types/main';
import { Part } from '@src/lib/types/universal';
import { Part, TextWeightType } from '@src/lib/types/universal';

export const FIRST_INTRO_CONTENT = 1;
export const LAST_INTRO_CONTENT = 3;
Expand Down Expand Up @@ -412,3 +414,54 @@ export const keywordList: KeywordListType = {
},
],
};

export const OWN_ORGANIZATION_LIST: {
nameKor: string;
nameEng: string;
description: TextWeightType[];
frontSideBg: string;
backSideBg: string;
}[] = [
{
nameKor: '메이커스',
nameEng: 'Makers',
description: [
{ content: 'SOPT를 한 기수 이상 수료한 사람들이 모여 ', weight: 'normal' },
{ content: 'SOPT에 필요한 프로덕트를 만드는 정식 기구', weight: 'bold' },
{
content:
'입니다. 3천여 명의 구성원들을 연결하고 새로운 가치를 제공하기 위한 방법을 끊임없이 고민해요. ',
weight: 'normal',
},
{ content: '앞으로도 SOPT를 지속적으로 운영하고자, ', weight: 'bold' },
{
content:
'어떻게 하면 우리의 활동이 더 즐거울 수 있을지, 대내외적으로 잘 알릴 수 있을지 고민할 거예요. ',
weight: 'normal',
},
],
frontSideBg: ImgMakersCard.src,
backSideBg: '#FF7C53',
},
{
nameKor: '마인드',
nameEng: 'Mind',
description: [
{ content: 'SOPT MIND는 SOPT 내외에 ', weight: 'normal' },
{ content: '기업가정신과 창업도전 문화 확산 목적', weight: 'bold' },
{
content:
'으로 설립된 기구입니다. 매 기수 SOPT 앱잼 팀이 더 적극적이고 똑똑하게 창업에 도전할 수 있도록 필요한 컨텐츠와 시스템을 고민하고 있어요. ',
weight: 'normal',
},
{
content:
'SOPT가 창업동아리임을 잊지 않도록, 그리고 전국에 열정으로 도전하는 SOPT의 MIND가 널리 공유되도록 ',
weight: 'bold',
},
{ content: 'MIND도 도전하겠습니다.', weight: 'normal' },
],
frontSideBg: ImgMindCard.src,
backSideBg: '#F66FF8',
},
];
2 changes: 2 additions & 0 deletions src/views/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PartConfig from '@src/views/MainPage/components/PartConfig';
import Activity from './components/Activity';
import Banner from './components/Banner';
import Introduce from './components/Introduce';
import OwnOrganization from './components/OwnOrganization';
import ScrollInteractiveLogo from './components/ScrollInteractiveLogo';

function MainPage() {
Expand All @@ -15,6 +16,7 @@ function MainPage() {
<ScrollInteractiveLogo />
<Activity />
<PartConfig />
<OwnOrganization />
</PageLayout>
);
}
Expand Down
50 changes: 50 additions & 0 deletions src/views/MainPage/components/OwnOrganization/Card/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import FlippableCard from '@src/components/common/FlippableCard';
import { TextWeightType } from '@src/lib/types/universal';
import * as S from './style';

type OwnOrganizationCardProps = {
nameKor: string;
nameEng: string;
description: TextWeightType[];
frontSideBg: string;
backSideBg: string;
};

function Footer({ nameKor, nameEng }: Pick<OwnOrganizationCardProps, 'nameKor' | 'nameEng'>) {
return (
<S.FooterWrapper>
<S.FooterKorName>{nameKor}</S.FooterKorName>
<S.FooterEngName>{nameEng}</S.FooterEngName>
</S.FooterWrapper>
);
}

export default function OwnOrganizationCard({
nameKor,
nameEng,
description,
frontSideBg,
backSideBg,
}: OwnOrganizationCardProps) {
return (
<FlippableCard
frontContent={
<S.CardWrapper background={`url(${frontSideBg}) center`}>
<Footer nameKor={nameKor} nameEng={nameEng} />
</S.CardWrapper>
}
backContent={
<S.CardWrapper background={backSideBg}>
<S.ContentWrapper>
{description.map((textNode, index) => (
<S.TextWrapper key={index} weight={textNode.weight}>
{textNode.content}
</S.TextWrapper>
))}
</S.ContentWrapper>
<Footer nameKor={nameKor} nameEng={nameEng} />
</S.CardWrapper>
}
/>
);
}
134 changes: 134 additions & 0 deletions src/views/MainPage/components/OwnOrganization/Card/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';

export const CardWrapper = styled.div<{ background: string }>`
background: ${({ background }) => background};
background-position: center;
background-size: cover;
background-repeat: no-repeat;
border-radius: 19px;
padding: 39px 0;
height: 380px;
display: flex;
flex-direction: column;
justify-content: flex-end;
@media (max-width: 1440px) {
width: 512px;
height: 432px;
padding-top: 39px;
padding-bottom: 23px;
}
@media (max-width: 768px) {
width: max(416px, min(100vw - 200px, 512px));
height: calc(max(432px, min(100vw - 200px, 512px)) * 0.84);
}
@media (max-width: 428px) {
width: 293px;
height: 250px;
padding-top: 20px;
padding-bottom: 13px;
}
`;

export const FooterKorName = styled.div`
width: 144px;
text-align: center;
padding: 16px 0;
color: ${colors.white};
border: 1px solid rgba(255, 255, 255, 0.5);
background: rgba(117, 97, 79, 0.33);
backdrop-filter: blur(2.949289321899414px);
border-radius: 14px;
font-size: 22px;
font-weight: 600;
line-height: 28px;
letter-spacing: -0.904px;
@media (max-width: 1440px) {
width: 128px;
padding: 12px 0;
font-size: 21px;
line-height: 24.425px;
}
@media (max-width: 428px) {
border-radius: 6px;
width: 74px;
padding: 7px 0;
font-size: 12px;
line-height: 13px;
}
`;

export const FooterEngName = styled.div`
color: rgba(255, 255, 255, 0.7);
font-family: SUIT;
font-size: 20px;
font-style: normal;
font-weight: 400;
line-height: 28.288px; /* 138.027% */
letter-spacing: -1.025px;
padding-bottom: 4px;
@media (max-width: 1440px) {
font-size: 19px;
line-height: 13.9px;
}
@media (max-width: 428px) {
font-size: 11px;
line-height: 14.9px;
}
`;

export const FooterWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: flex-end;
padding-left: 30px;
padding-right: 42px;
@media (max-width: 1440px) {
padding-left: 25px;
padding-right: 27px;
}
@media (max-width: 428px) {
padding-left: 14px;
padding-right: 15px;
}
`;

export const ContentWrapper = styled.div`
padding: 0 41px;
flex: 1;
word-break: keep-all;
@media (max-width: 428px) {
padding: 0 20px;
}
`;

export const TextWrapper = styled.span<{ weight: 'normal' | 'bold' }>`
font-size: 20px;
color: ${colors.white};
font-weight: ${({ weight }) => weight};
line-height: 35px; /* 175% */
letter-spacing: -0.8px;
@media (max-width: 1440px) {
font-size: 18px;
line-height: 31px; /* 172.222% */
letter-spacing: -0.72px;
}
@media (max-width: 428px) {
font-size: 11px;
line-height: 18.103px; /* 164.575% */
letter-spacing: -0.44px;
}
`;
23 changes: 23 additions & 0 deletions src/views/MainPage/components/OwnOrganization/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { OWN_ORGANIZATION_LIST } from '@src/lib/constants/main';
import Tab from '../Tab';
import OwnOrganizationCard from './Card';
import * as S from './style';

export default function OwnOrganization() {
return (
<S.Background>
<Tab
tab={'(3) 자체 운영 기구'}
title={'SOPT를 운영하는 자체 기구'}
description={
'SOPT에는 솝트를 자체적으로 운영하는 두 가지의 기구가 존재합니다. 한 기수 이상 활동한\n사람들이 모여, 솝트가 보다 유연하고 열정적인 경험으로 채워질 수 있도록 노력하죠.'
}
/>
<S.Wrapper>
{OWN_ORGANIZATION_LIST.map((organization) => (
<OwnOrganizationCard key={organization.nameEng} {...organization} />
))}
</S.Wrapper>
</S.Background>
);
}
22 changes: 22 additions & 0 deletions src/views/MainPage/components/OwnOrganization/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';

export const Wrapper = styled.div`
display: flex;
gap: 28px;
overflow-x: hidden;
@media (max-width: 1440px) {
gap: 24px;
overflow-x: scroll;
}
@media (max-width: 428px) {
gap: 14px;
}
`;

export const Background = styled.section`
background-color: ${colors.white};
padding-top: 146px;
`;

0 comments on commit 5d26f80

Please sign in to comment.