Skip to content

Commit

Permalink
Merge pull request #173 from woowacourse-teams/feature/CK-210
Browse files Browse the repository at this point in the history
[feat/CK-210] ๋กœ๋“œ๋งต ๋””ํ…Œ์ผ ํŽ˜์ด์ง€์˜ UI๋ฅผ ๊ฐœํŽธํ•œ๋‹ค.
  • Loading branch information
jw-r authored Oct 1, 2023
2 parents ce9c5c7 + 0fa6668 commit b60c3e3
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 52 deletions.
15 changes: 15 additions & 0 deletions client/src/components/icons/svgIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2488,3 +2488,18 @@ export const RightIcon = ({ width, ...props }: SVGProps<SVGSVGElement>) => (
<path d='M9 18l6-6-6-6' />
</svg>
);

export const NoImageIcon = ({ width, ...props }: SVGProps<SVGSVGElement>) => (
<svg
{...props}
xmlns='http://www.w3.org/2000/svg'
width={width}
height={width}
viewBox='0 0 32 32'
>
<path
fill='currentColor'
d='M30 3.414L28.586 2L2 28.586L3.414 30l2-2H26a2.003 2.003 0 0 0 2-2V5.414zM26 26H7.414l7.793-7.793l2.379 2.379a2 2 0 0 0 2.828 0L22 19l4 3.997zm0-5.832l-2.586-2.586a2 2 0 0 0-2.828 0L19 19.168l-2.377-2.377L26 7.414zM6 22v-3l5-4.997l1.373 1.374l1.416-1.416l-1.375-1.375a2 2 0 0 0-2.828 0L6 16.172V6h16V4H6a2.002 2.002 0 0 0-2 2v16z'
/>
</svg>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import styled from 'styled-components';
import media from '@styles/media';

export const ExtraInfo = styled.div`
${({ theme }) => theme.fonts.description5};
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: space-between;
width: 30%;
height: 55rem;
${media.mobile`
display: none;
`}
`;

export const RoadmapMetadata = styled.div`
display: flex;
flex-direction: column;
& > div:not(:last-child) {
margin-bottom: 3rem;
}
`;

export const Category = styled.div`
display: flex;
align-items: center;
justify-content: flex-end;
`;

export const Difficulty = styled.div`
text-align: end;
`;

export const RecommendedRoadmapPeriod = styled.div`
text-align: end;
`;

export const Tags = styled.div`
color: ${({ theme }) => theme.colors.main_dark};
& > div {
text-align: end;
}
`;
33 changes: 33 additions & 0 deletions client/src/components/roadmapDetailPage/extraInfo/ExtraInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { RoadmapDetailType } from '@myTypes/roadmap/internal';
import * as S from './ExtraInfo.styles';
import SVGIcon from '@components/icons/SVGIcon';
import { CategoriesInfo } from '@constants/roadmap/category';

type ExtraInfoProps = {
roadmapInfo: RoadmapDetailType;
};

const ExtraInfo = ({ roadmapInfo }: ExtraInfoProps) => {
return (
<S.ExtraInfo>
<div>Created by {roadmapInfo.creator.name}</div>
<S.RoadmapMetadata>
<S.Category>
์นดํ…Œ๊ณ ๋ฆฌ: {roadmapInfo.category.name}
<SVGIcon name={CategoriesInfo[roadmapInfo.category.id].iconName} />
</S.Category>
<S.Difficulty>๋‚œ์ด๋„: {roadmapInfo.difficulty}</S.Difficulty>
<S.RecommendedRoadmapPeriod>
์˜ˆ์ƒ ์†Œ์š”์‹œ๊ฐ„: {roadmapInfo.recommendedRoadmapPeriod}์ผ
</S.RecommendedRoadmapPeriod>
</S.RoadmapMetadata>
<S.Tags>
{roadmapInfo.tags.map((tag) => (
<div key={tag.id}>#{tag.name}</div>
))}
</S.Tags>
</S.ExtraInfo>
);
};

export default ExtraInfo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import media from '@styles/media';
import styled from 'styled-components';

export const IntroductionWrapper = styled.div`
width: 70%;
${media.mobile`
width:100%;
`}
`;

export const Introduction = styled.div<{ isExpanded: boolean }>`
${({ theme }) => theme.fonts.description5};
overflow: hidden;
max-height: ${({ isExpanded }) => (isExpanded ? 'auto' : '55rem')};
& > p:not(:last-child) {
margin-bottom: 2rem;
}
& div {
${({ theme }) => theme.fonts.h1};
margin-bottom: 0.5rem;
color: ${({ theme }) => theme.colors.main_dark};
}
`;

export const LineShadow = styled.div`
position: relative;
width: 100%;
height: 0.2rem;
box-shadow: 0 -4px 6px rgba(0, 0, 0, 1);
`;

export const ReadMoreButton = styled.button`
position: relative;
top: calc(-2rem - 4px);
left: 50%;
transform: translateX(-5rem);
width: 10rem;
height: 4rem;
background-color: ${({ theme }) => theme.colors.white};
border-radius: 8px;
box-shadow: ${({ theme }) => theme.shadows.main};
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { RoadmapDetailType } from '@myTypes/roadmap/internal';
import * as S from './Introduction.styles';
import { useEffect, useRef, useState } from 'react';

type IntroductionProps = {
roadmapInfo: RoadmapDetailType;
};

const Introduction = ({ roadmapInfo }: IntroductionProps) => {
const [isExpanded, setIsExpanded] = useState(false);
const [showMoreButton, setShowMoreButton] = useState(false);
const introRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (!introRef.current) return;

const element = introRef.current;
if (element.scrollHeight > element.clientHeight) {
setShowMoreButton(true);
}
}, []);

const toggleExpand = () => {
setIsExpanded((prev) => !prev);
};

return (
<S.IntroductionWrapper>
<S.Introduction isExpanded={isExpanded} ref={introRef}>
<p>
<div>์„ค๋ช…</div>
{roadmapInfo.introduction}
</p>
<p>
<div>๋ณธ๋ฌธ</div>
{roadmapInfo.content.content === ''
? '๋กœ๋“œ๋งต์— ๋Œ€ํ•œ ์„ค๋ช…์ด ์—†์–ด์š”๐Ÿฅฒ'
: roadmapInfo.content.content}
</p>
</S.Introduction>
{showMoreButton && !isExpanded && (
<>
<S.LineShadow />
<S.ReadMoreButton onClick={toggleExpand}>๋” ๋ณด๊ธฐ</S.ReadMoreButton>
</>
)}
</S.IntroductionWrapper>
);
};

export default Introduction;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import styled from 'styled-components';
import media from '@styles/media';

export const SliderContent = styled.div`
display: flex;
aspect-ratio: 5 / 3.5;
background-color: ${({ theme }) => theme.colors.gray100};
border-radius: 8px;
${media.mobile`
aspect-ratio: 0;
`}
`;

export const LeftContent = styled.div`
width: 45%;
${media.mobile`
display: none;
`}
`;

export const NodeImg = styled.img`
width: 100%;
height: 100%;
padding: 1.5rem;
object-fit: cover;
`;

export const NoImg = styled.div`
${({ theme }) => theme.fonts.title_large}
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
`;

export const Separator = styled.div`
display: flex;
flex-direction: column;
width: 0.2rem;
height: 100%;
& > div {
height: 50%;
}
& > div:last-child {
background-color: black;
}
`;

export const RightContent = styled.div`
${({ theme }) => theme.fonts.h1}
overflow: scroll;
width: 55%;
padding: 1.5rem;
padding-top: 3rem;
${media.mobile`
width: 100%;
height: 60rem;
padding-top: 1.5rem;
`}
`;

export const ContentTitle = styled.div`
${({ theme }) => theme.fonts.title_large}
display: flex;
align-items: center;
margin-bottom: 1rem;
`;

export const Step = styled.div`
${({ theme }) => theme.fonts.h2}
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
margin-right: 0.5rem;
border: 0.3rem solid black;
border-radius: 50%;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { NodeType } from '@myTypes/roadmap/internal';
import * as S from './NodeContent.styles';
import SVGIcon from '@components/icons/SVGIcon';

type NodeContentProps = {
node: NodeType;
index: number;
};

const NodeContent = ({ node, index }: NodeContentProps) => {
return (
<S.SliderContent key={node.id}>
<S.LeftContent>
{node.imageUrls[0] ? (
<S.NodeImg src={node.imageUrls[0]} />
) : (
<S.NoImg>
<SVGIcon name='NoImageIcon' size={100} />
<div>No Image</div>
</S.NoImg>
)}
</S.LeftContent>
<S.Separator>
<div />
<div />
</S.Separator>
<S.RightContent>
<S.ContentTitle>
<S.Step>{index + 1}</S.Step>
<p>{node.title}</p>
</S.ContentTitle>
{node.description}
</S.RightContent>
</S.SliderContent>
);
};

export default NodeContent;
Loading

0 comments on commit b60c3e3

Please sign in to comment.