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

design: 톡앤픽 플레이스 Page UI 구현 #155

Merged
merged 7 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import SearchResultPage from './pages/SearchResultPage/SearchResultPage';
import SignUpPage from './pages/SignUpPage/SignUpPage';
import { useNewSelector } from './store';
import { selectAccessToken } from './store/auth';
import TalkPickPlacePage from './pages/TalkPickPlacePage/TalkPickPlacePage';

const App: React.FC = () => {
const accessToken = useNewSelector(selectAccessToken);
Expand All @@ -38,6 +39,7 @@ const App: React.FC = () => {
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<LandingPage />} />
<Route path="/talkpickplace" element={<TalkPickPlacePage />} />
{/* <Route path="posts" element={<PostList />} />
<Route path="posts/:id" element={<PostPage />} />
<Route path="searchResult" element={<SearchResultPage />} />
Expand Down
1 change: 1 addition & 0 deletions src/assets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export { default as Popular } from './svg/popular.svg';
export { default as Couple } from './svg/couple.svg';
export { default as Taste } from './svg/taste.svg';
export { default as Worldcup } from './svg/worldcup.svg';
export { default as TalkPickBubble } from './svg/talk-pick-bubble.svg';

// TODO: 이전 SVG
export { default as Email } from './svg/email.svg';
Expand Down
9 changes: 9 additions & 0 deletions src/assets/svg/talk-pick-bubble.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 104 additions & 0 deletions src/components/atoms/TalkPickItem/TalkPickItem.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { css } from '@emotion/react';
import typo from '@/styles/typo';
import color from '@/styles/color';
import type { TalkPickListItemProps } from './TalkPickItem';

export const commonNumberStyle = css(typo.Number.Medium, {
color: color.GY[1],
});

export const bestNumberStyle = css(typo.Number.Medium, {
color: color.MAIN,
});

export const commonStyle = css(typo.Comment.SemiBold, {
color: color.GY[1],
});

export const headerStyle = css(typo.Main.Medium, {
color: color.BK,
});

export const borderBottomStyling = css({
borderBottom: '1px solid #F4F4F4',
});

export const centerStyling = css({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
});

export const talkPickListItemStyling = css({
display: 'flex',
alignItems: 'center',
width: '1174px',
height: '60px',
});

export const talkPickListId = css([
centerStyling,
{
width: '112px',
color: color.GY[1],
},
]);

export const getTalkPickListIdStyling = (
type: Required<TalkPickListItemProps>['type'],
) => {
return type === 'best' ? bestNumberStyle : commonNumberStyle;
};

export const talkPickListTitle = css({
width: '570px',
padding: '0 10px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
color: color.BK,
});

export const talkPickTitleText = css({
cursor: 'pointer',
});

export const getTalkPickListTitleStyling = (
type: Required<TalkPickListItemProps>['type'],
) => {
const style = {
header: css(typo.Main.Medium, centerStyling),
default: css(typo.Main.Medium),
best: css(typo.Main.SemiBold, {
fontWeight: 'bold',
}),
};

return style[type];
};

export const getTalkPickListWriterStyling = (
type: Required<TalkPickListItemProps>['type'],
) => {
return type === 'header' ? headerStyle : commonStyle;
};

export const talkPickListWideDetail = css([
centerStyling,
{
width: '148px',
},
]);

export const talkPickListDetail = css([
centerStyling,
{
width: '85px',
},
]);

export const getTalkPickListDetailStyling = (
type: Required<TalkPickListItemProps>['type'],
) => {
return type === 'header' ? headerStyle : commonNumberStyle;
};
77 changes: 77 additions & 0 deletions src/components/atoms/TalkPickItem/TalkPickItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';
import { TalkPickListItem } from '@/types/talk-pick';
import { formatDate, formatNumber } from '@/utils/formatData';
import * as S from './TalkPickItem.style';

export interface TalkPickListItemProps {
type?: 'header' | 'default' | 'best';
rank?: number;
talkPickItem?: TalkPickListItem;
}

const headerTalkPick: TalkPickListItem = {
id: 0,
title: '제목',
writer: '작성자',
createdAt: '작성일시',
views: '조회수',
bookmarks: '저장수',
};

const TalkPickItem = ({
type = 'default',
rank,
talkPickItem = headerTalkPick,
}: TalkPickListItemProps) => {
const getTalkPickId = (): number | undefined => {
switch (type) {
case 'default':
return talkPickItem.id;
case 'best':
return rank;
case 'header':
default:
return undefined;
}
};
Comment on lines +26 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

talkpickId를 props 로 받게 된다면, case에 따른 로직을 utils에 정의하는 것도 좋아보여요 😄


const getFormatNumber = (item: number | string): string => {
return typeof item === 'number' ? formatNumber(item) : item;
};

return (
<div
css={[
S.talkPickListItemStyling,
type !== 'header' && S.borderBottomStyling,
]}
>
<div css={[S.talkPickListId, S.getTalkPickListIdStyling(type)]}>
{getTalkPickId()}
</div>
<div css={[S.talkPickListTitle, S.getTalkPickListTitleStyling(type)]}>
<span css={type !== 'header' && S.talkPickTitleText}>
{talkPickItem.title}
</span>
</div>
<div
css={[S.talkPickListWideDetail, S.getTalkPickListWriterStyling(type)]}
>
{talkPickItem.writer}
</div>
<div
css={[S.talkPickListWideDetail, S.getTalkPickListDetailStyling(type)]}
>
{formatDate(talkPickItem.createdAt)}
</div>
<div css={[S.talkPickListDetail, S.getTalkPickListDetailStyling(type)]}>
{getFormatNumber(talkPickItem.views)}
</div>
<div css={[S.talkPickListDetail, S.getTalkPickListDetailStyling(type)]}>
{getFormatNumber(talkPickItem.bookmarks)}
</div>
</div>
);
};

export default TalkPickItem;
18 changes: 18 additions & 0 deletions src/components/molecules/BestTalkPick/BestTalkPick.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { css } from '@emotion/react';
import typo from '@/styles/typo';
import color from '@/styles/color';

export const bestTalkPickContainer = css({
display: 'flex',
flexDirection: 'column',
paddingTop: '30px',
paddingBottom: '40px',
borderRadius: '20px',
border: `1px solid ${color.GY[2]}`,
boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
});

export const bestTalkPickText = css(typo.Title, {
padding: '0 40px',
color: color.MAIN,
});
25 changes: 25 additions & 0 deletions src/components/molecules/BestTalkPick/BestTalkPick.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import { TalkPickListItem } from '@/types/talk-pick';
import TalkPickItem from '@/components/atoms/TalkPickItem/TalkPickItem';
import * as S from './BestTalkPick.style';

export interface BestTalkPickProps {
bestTalkPick: TalkPickListItem[];
}

const BestTalkPick = ({ bestTalkPick }: BestTalkPickProps) => (
<div css={S.bestTalkPickContainer}>
<div css={S.bestTalkPickText}>BEST 3</div>
<TalkPickItem type="header" />
{bestTalkPick.map((talkPick, idx) => (
<TalkPickItem
key={talkPick.id}
type="best"
rank={idx + 1}
talkPickItem={talkPick}
/>
))}
</div>
);

export default BestTalkPick;
14 changes: 14 additions & 0 deletions src/components/molecules/TalkPickList/TalkPickList.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { css } from '@emotion/react';
import color from '@/styles/color';

export const talkPickListContainer = css({
display: 'flex',
flexDirection: 'column',
padding: '12px 0',
borderTop: `1px solid ${color.GY[2]}`,
});

export const talkPickListWrapper = css({
display: 'flex',
flexDirection: 'column',
});
25 changes: 25 additions & 0 deletions src/components/molecules/TalkPickList/TalkPickList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import { TalkPickListItem } from '@/types/talk-pick';
import TalkPickItem from '@/components/atoms/TalkPickItem/TalkPickItem';
import * as S from './TalkPickList.style';

export interface TalkPickListProps {
talkPickList: TalkPickListItem[];
}

const TalkPickList = ({ talkPickList }: TalkPickListProps) => (
<div css={S.talkPickListContainer}>
<div css={S.talkPickListWrapper}>
<TalkPickItem type="header" />
{talkPickList.map((talkPick) => (
<TalkPickItem
key={talkPick.id}
type="default"
talkPickItem={talkPick}
/>
))}
</div>
</div>
);

export default TalkPickList;
2 changes: 1 addition & 1 deletion src/components/organisms/Footer/Footer.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const footerContainer = css`
display: flex;
flex-direction: column;
background-color: ${color.BLUE_LIGHT};
width: 1920px;
width: 100%;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

header와 footer의 경우, 전체 layout을 , 나머지 요소들은 양 옆 간격을 가지고 표시되기 때문에 1920px 로 지정해놨었는데, 100%로 처리하고 안에 요소들에 margin 을 설정하는 것도 좋은 방법이네요!

height: 427px;
padding-left: 200px;
`;
Expand Down
3 changes: 2 additions & 1 deletion src/components/organisms/Header/Header.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const containerStyle = css({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#ffffff',
backgroundColor: color.WT,
boxShadow: '0px 4px 11px rgba(0, 0, 0, 0.1)',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이부분 저도 이번에 확인하고 수정했는데..! 감사합니다🙂‍↕️

});

export const logoStyle = css({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { css } from '@emotion/react';

export const talkPickListContainer = css({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
});

export const talkPickBtnWrapper = css({
display: 'flex',
justifyContent: 'space-between',
width: '100%',
alignItems: 'flex-end',
padding: '0 5px',
});

export const talkPickListWrapper = css({
paddingTop: '10px',
paddingBottom: '60px',
});

export const talkPickWriteBtnWrapper = css({
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-end',
gap: '5px',
});

export const talkPickWriteBtn = css({
width: '108px',
marginRight: '5px',
});
Loading
Loading