Skip to content

Commit

Permalink
Merge pull request #64 from Team-Lecue/feature/DetailPage
Browse files Browse the repository at this point in the history
[ DetailPage ] dev 머지 PR입니다!
  • Loading branch information
jungwoo3490 committed Jan 10, 2024
2 parents e10db9c + 44e2091 commit 2b0f6ce
Show file tree
Hide file tree
Showing 28 changed files with 728 additions and 18 deletions.
Empty file added src/Detail/components/.gitkeep
Empty file.
93 changes: 93 additions & 0 deletions src/Detail/components/BookInfoBox/BookInfoBox.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import styled from '@emotion/styled';

export const BookInfoBoxWrapper = styled.div<{ backgroundColor: number }>`
display: flex;
width: 100%;
height: 18.3em;
background-color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return theme.colors.BG;
case 1:
return theme.colors.white;
}
}};
`;

export const ProfileImageWrapper = styled.div`
display: flex;
align-items: center;
margin-left: 1.6rem;
`;

export const ProfileImg = styled.img`
width: 12.6rem;
height: 12.6rem;
border-radius: 8.2rem;
object-fit: cover;
`;

export const BookInfoWrapper = styled.div`
padding: 2.2rem 1.7rem;
`;

export const BookInfoHeader = styled.div`
display: flex;
align-items: center;
column-gap: 0.9rem;
`;

export const BookInfoHeaderItemWrapper = styled.div`
display: flex;
align-items: center;
column-gap: 0.3rem;
`;

export const BookInfoHeaderItem = styled.p<{ backgroundColor: number }>`
height: 1.8rem;
padding-top: 0.4rem;
color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return 'rgba(255, 255, 255, 0.3)';
case 1:
return theme.colors.MG;
}
}};
${({ theme }) => theme.fonts.E_Caption_R_12};
`;

export const BookInfoTitle = styled.p<{ backgroundColor: number }>`
margin-top: 0.7rem;
color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return theme.colors.white;
case 1:
return theme.colors.BG;
}
}};
${({ theme }) => theme.fonts.Head2_SB_18};
`;

export const BookInfoContent = styled.p<{ backgroundColor: number }>`
height: 8.5rem;
margin-top: 1rem;
color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return 'rgba(255, 255, 255, 0.8)';
case 1:
return theme.colors.BG;
}
}};
${({ theme }) => theme.fonts.Body3_R_14};
`;
52 changes: 52 additions & 0 deletions src/Detail/components/BookInfoBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { IcCrown, IcDate } from '../../../assets';
import * as S from './BookInfoBox.style';

interface BookInfoBoxProps {
profileImg: string;
date: string;
nickname: string;
title: string;
content: string;
backgroundColor: number;
}

function BookInfoBox({
profileImg,
date,
nickname,
title,
content,
backgroundColor,
}: BookInfoBoxProps) {
return (
<S.BookInfoBoxWrapper backgroundColor={backgroundColor}>
<S.ProfileImageWrapper>
<S.ProfileImg src={profileImg} />
</S.ProfileImageWrapper>
<S.BookInfoWrapper>
<S.BookInfoHeader>
<S.BookInfoHeaderItemWrapper>
<IcDate />
<S.BookInfoHeaderItem backgroundColor={backgroundColor}>
{date}
</S.BookInfoHeaderItem>
</S.BookInfoHeaderItemWrapper>
<S.BookInfoHeaderItemWrapper>
<IcCrown />
<S.BookInfoHeaderItem backgroundColor={backgroundColor}>
{nickname}
</S.BookInfoHeaderItem>
</S.BookInfoHeaderItemWrapper>
</S.BookInfoHeader>
<S.BookInfoTitle backgroundColor={backgroundColor}>
{title}
</S.BookInfoTitle>
<S.BookInfoContent backgroundColor={backgroundColor}>
{content}
</S.BookInfoContent>
</S.BookInfoWrapper>
</S.BookInfoBoxWrapper>
);
}

export default BookInfoBox;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import styled from '@emotion/styled';

export const LecueNoteListHeaderWrapper = styled.div<{
backgroundColor: number;
}>`
display: flex;
position: sticky;
top: 9.8rem;
z-index: 2;
padding: 1.2rem 1.65rem 0;
background-color: transparent;
column-gap: 1rem;
`;

export const LecueNoteCountBox = styled.div<{ backgroundColor: number }>`
display: flex;
justify-content: center;
align-items: center;
padding: 1.05rem 1.8rem;
border-radius: 7rem;
background-color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return theme.colors.BG;
case 1:
return theme.colors.white;
}
}};
color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return theme.colors.white;
case 1:
return theme.colors.BG;
}
}};
${({ theme }) => theme.fonts.E_Body2_R_14};
`;

export const LecueNoteRenderModeButton = styled.button`
position: relative;
z-index: 2;
width: 3.8rem;
height: 3.8rem;
`;
29 changes: 29 additions & 0 deletions src/Detail/components/LecueNoteLIstHeader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BtnFloatingList, BtnFloatingPostit } from '../../../assets';
import * as S from './LecueNoteListHeader.style';

interface LecueNoteListHeaderProps {
noteNum: number;
backgroundColor: number;
isZigZagView: boolean;
buttonOnClick: () => void;
}

function LecueNoteListHeader({
noteNum,
backgroundColor,
isZigZagView,
buttonOnClick,
}: LecueNoteListHeaderProps) {
return (
<S.LecueNoteListHeaderWrapper backgroundColor={backgroundColor}>
<S.LecueNoteCountBox
backgroundColor={backgroundColor}
>{`${noteNum}개`}</S.LecueNoteCountBox>
<S.LecueNoteRenderModeButton type="button" onClick={buttonOnClick}>
{isZigZagView ? <BtnFloatingList /> : <BtnFloatingPostit />}
</S.LecueNoteRenderModeButton>
</S.LecueNoteListHeaderWrapper>
);
}

export default LecueNoteListHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from '@emotion/styled';

export const LecueNoteListContainerWrapper = styled.div<{
backgroundColor: number;
}>`
padding: 0 1.65rem;
background-color: ${({ theme, backgroundColor }) => {
switch (backgroundColor) {
case 0:
return theme.colors.white;
case 1:
return theme.colors.BG;
}
}};
flex: 1;
`;
45 changes: 45 additions & 0 deletions src/Detail/components/LecueNoteListContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useState } from 'react';

import LecueNoteListHeader from '../LecueNoteLIstHeader';
import ZigZagView from '../ZigZagView';
import * as S from './LecueNoteListContainer.style';

interface Note {
noteId: number;
renderType: number;
content: string;
noteDate: string;
noteNickname: string;
noteBackgroundColor: number;
}

interface LecueNoteListContainerProps {
noteNum: number;
backgroundColor: number;
noteList: Note[];
}

function LecueNoteListContainer({
noteNum,
backgroundColor,
noteList,
}: LecueNoteListContainerProps) {
const [isZigZagView, setIsZigZagView] = useState<boolean>(true);
return (
<S.LecueNoteListContainerWrapper backgroundColor={backgroundColor}>
<LecueNoteListHeader
noteNum={noteNum}
backgroundColor={backgroundColor}
isZigZagView={isZigZagView}
buttonOnClick={() => setIsZigZagView(!isZigZagView)}
/>
{isZigZagView ? (
<ZigZagView noteList={noteList} />
) : (
<ZigZagView noteList={noteList} />
)}
</S.LecueNoteListContainerWrapper>
);
}

export default LecueNoteListContainer;
47 changes: 47 additions & 0 deletions src/Detail/components/SlideBanner/SlideBanner.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';

export const infiniteSlide = keyframes`
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
`;

export const SliderBannerWrapper = styled.div`
position: fixed;
overflow: hidden;
z-index: 1;
width: 100%;
height: 4.4rem;
border-bottom: 0.1rem solid ${({ theme }) => theme.colors.BG};
background-color: ${({ theme }) => theme.colors.key};
`;

export const AnimationBox = styled.div<{
width: number;
animationDuration: number;
}>`
display: flex;
width: ${(props) => props.width}rem;
height: 100%;
animation: ${infiniteSlide};
animation-duration: ${(props) => props.animationDuration}s;
animation-timing-function: linear;
animation-iteration-count: infinite;
`;

export const SlideBannerItemList = styled.div<{ width: number }>`
display: flex;
align-items: center;
width: ${(props) => props.width}rem;
height: 100%;
`;
54 changes: 54 additions & 0 deletions src/Detail/components/SlideBanner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useEffect, useRef, useState } from 'react';

import SlideBannerItem from '../SlideBannerItem';
import * as S from './SlideBanner.style';

interface SlideBannerProps {
name: string;
}

function SlideBanner({ name }: SlideBannerProps) {
const itemBoxRef = useRef<HTMLDivElement | null>(null);
const [itemListWidth, setItemListWidth] = useState(0);
const [animationListWidth, setAnimationListWidth] = useState(0);
const [animationDuration, setAnimationDuration] = useState(10);

const renderSlideBannerItems = () => {
return Array.from({ length: 10 }, (_, index) => (
<SlideBannerItem key={index} ref={itemBoxRef} name={name} />
));
};

useEffect(() => {
if (itemBoxRef.current) {
const itemBoxWidth = itemBoxRef.current.offsetWidth;

const itemListWidth = itemBoxWidth + 6;

setItemListWidth(itemListWidth);
setAnimationListWidth(itemListWidth * 2);

const nameLength = name.length;
const newAnimationDuration = Math.max(1, nameLength * 7);
setAnimationDuration(newAnimationDuration);
}
}, [name]);

return (
<S.SliderBannerWrapper>
<S.AnimationBox
width={animationListWidth}
animationDuration={animationDuration}
>
<S.SlideBannerItemList width={itemListWidth}>
{renderSlideBannerItems()}
</S.SlideBannerItemList>
<S.SlideBannerItemList width={itemListWidth}>
{renderSlideBannerItems()}
</S.SlideBannerItemList>
</S.AnimationBox>
</S.SliderBannerWrapper>
);
}

export default SlideBanner;
Loading

0 comments on commit 2b0f6ce

Please sign in to comment.