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

Feat: 리스트 상세페이지 안쪽 레이아웃 퍼블리싱 #15

Merged
merged 46 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
91eb607
Design : 리스트 상세페이지 내부의 rankList 컴포넌트 레이아웃 생성
kanglocal Jan 29, 2024
918ec84
Design : 리스트 상세페이지 내부의 rankList 컴포넌트 스타일 적용
kanglocal Jan 29, 2024
9f031bf
Fix : 리스트 상세페이지 내부의 rankList 컴포넌트 스타일 및 타입 수정
kanglocal Jan 29, 2024
6c70a71
Design : 리스트 상세페이지 내부의 rankList 컴포넌트 스타일 수정
kanglocal Jan 29, 2024
03328bf
Design : 리스트 상세페이지 내부의 rankList 컴포넌트에 바텀시트 추가
kanglocal Jan 31, 2024
5260285
Chore : open-graph 라이브러리 설치
kanglocal Jan 31, 2024
ceca2ea
Chore : open-graph 라이브러리 타입 설치
kanglocal Jan 31, 2024
b89db45
Chore : cheerio 라이브러리 설치
kanglocal Jan 31, 2024
7fde5f0
feat : 링크 미리보기 기능 일부 구현
kanglocal Jan 31, 2024
08b9252
style : 링크 미리보기 코드 수정
kanglocal Jan 31, 2024
292fbf7
Design : rankList 스타일 변경
kanglocal Jan 31, 2024
250b759
Feature : 비디오 임베드 추가 및 스타일 변경
kanglocal Feb 1, 2024
4723e2e
Style : 주석 수정
kanglocal Feb 1, 2024
f31b0b7
Chore : copy-to-clipboard 라이브러리 다운로드
kanglocal Feb 1, 2024
20971db
Feature : 링크 다운로드 기능 구현
kanglocal Feb 1, 2024
dea6474
Chore : react-toastify 다운로드
kanglocal Feb 1, 2024
3fcbad3
Feature : 토스트 구현
kanglocal Feb 1, 2024
da2e056
Chore : html-to-image 라이브러리 다운로드
kanglocal Feb 1, 2024
aaa72c6
Feature : 리스트상세의 이미지 저장 기능 구현 초안
kanglocal Feb 3, 2024
6da3a8c
Feature : 카카오톡 공유기 초안
kanglocal Feb 3, 2024
f7b372a
Feature : OG태그 불러오는 로직을 프록시로 이동
kanglocal Feb 3, 2024
8d60c1f
Fix : 목데이터 제거 및 코드 정리
kanglocal Feb 3, 2024
d5687d0
Fix : 프록시 설정
kanglocal Feb 3, 2024
668609c
Fix : 컴포넌트명 변경
kanglocal Feb 3, 2024
6101a8a
Fix : 컴포넌트명 변경
kanglocal Feb 3, 2024
1fb34c0
Style : css파일 컨벤션에 맞춰 수정 및 폴더 구조 변경
kanglocal Feb 3, 2024
332575e
fix : layout.tsx에 카카오 sdk, toastContainer 추가
kanglocal Feb 3, 2024
eaa8444
fix : 카카오톡 공유 템플릿 변경
kanglocal Feb 3, 2024
30d5a43
fix : 링크 미리보기 수정
kanglocal Feb 3, 2024
c3a2490
Design : rankList css 수정
kanglocal Feb 4, 2024
2685880
fix : img태그 -> Image로 수정
kanglocal Feb 4, 2024
2bd4c0c
Chore : yarn.lock 커밋
kanglocal Feb 4, 2024
584b6f1
fix : img태그 -> Image태그
kanglocal Feb 4, 2024
20b7633
fix : 사용하지 않는 파일 삭제
kanglocal Feb 4, 2024
eba8ed8
Merge remote-tracking branch 'upstream/dev' into feature/list_detail_…
kanglocal Feb 4, 2024
b7794b3
fix : Image -> img
kanglocal Feb 4, 2024
6430315
Design : 나현님 css에맞춰 수정
kanglocal Feb 4, 2024
f39effc
Merge remote-tracking branch 'upstream/dev' into feature/list_detail_…
kanglocal Feb 4, 2024
37b1606
Style : 불필요한 console.log 삭제
kanglocal Feb 4, 2024
e33c35c
Style : import 순서 변경
kanglocal Feb 4, 2024
89aa080
Style : CI/CD에서 잡아준 에러로 수정했습니다.
kanglocal Feb 4, 2024
c90d561
Style : TODO 주석 생성
kanglocal Feb 4, 2024
5a3b3a8
Style : CI/CD 에러 수정
kanglocal Feb 4, 2024
4627d2d
Style : 오타 수정
kanglocal Feb 4, 2024
dec085b
Style : TODO 주석 생성
kanglocal Feb 4, 2024
0462dd3
Style : CI/CD에러 수정
kanglocal Feb 5, 2024
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
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "temp",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:3000",
"scripts": {
"dev": "next dev",
"build": "next build",
Expand Down Expand Up @@ -31,12 +32,19 @@
"@vanilla-extract/next-plugin": "^2.3.2",
"@yaireo/tagify": "^4.19.0",
"axios": "^1.6.5",
"cheerio": "^1.0.0-rc.12",
"copy-to-clipboard": "^3.3.3",
"html-to-image": "^1.11.11",
"http-proxy-middleware": "^2.0.6",
"next": "14.0.4",
"open-graph": "^0.2.6",
"react": "^18",
"react-beautiful-dnd": "^13.1.1",
"react-dom": "^18",
"react-hook-form": "^7.50.0",
"react-scripts": "^5.0.1",
"react-select": "^5.8.0",
"react-toastify": "^10.0.4",
"zustand": "^4.4.7"
},
"devDependencies": {
Expand All @@ -51,6 +59,7 @@
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/jest": "^29.5.11",
"@types/node": "^20",
"@types/open-graph": "^0.2.5",
"@types/react": "^18",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "^18",
Expand Down
4 changes: 2 additions & 2 deletions public/icons/check_red.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/collect.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/icons/crown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/etc.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/share.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { keyframes, style } from '@vanilla-extract/css';

export const backGround = style({
position: 'fixed',
top: 0,
left: 0,
bottom: 0,
right: 0,
background: 'rgba(0,0,0,0.3)',
zIndex: 999,
});

export const wrapper = style({
padding: '37px 0 43px',

position: 'fixed',
bottom: 0,
left: 0,
right: 0,

display: 'flex',
flexDirection: 'column',
justifyContent: 'center',

backgroundColor: '#ffffff',
borderTopLeftRadius: '25px',
borderTopRightRadius: '25px',

transitionProperty: 'all',
transitionDuration: '0.2s',
});

const slideIn = keyframes({
from: { transform: 'translateY(100%)' },
to: { transform: 'translateY(0)' },
});
Comment on lines +33 to +36
Copy link
Contributor

Choose a reason for hiding this comment

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

바닐라익스트랙 keyframe 이렇게 쓰는거였군요,,!!!
왜인지 제 드롭다운은 스르륵이 적용 안 됐는데 이제야 이유를 알아갑니다,,🩷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

나현님께서 구현하신 부분입니다!!! 컨플릭트 없애려고 전전긍긍하다보니 제꺼로 들어와버렸네요...ㅠㅠㅠㅠㅠ
나현님최고!


export const sheetActive = style({
animation: `${slideIn} 0.2s ease-in-out`,
});

export const sheetItemWrapper = style({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',

':hover': {
backgroundColor: '#EFEFF0',
},
});

export const checkIcon = style({
display: 'none',
marginRight: '28px',

selectors: {
[`${sheetItemWrapper}:hover &`]: {
display: 'block',
},
},
});

export const sheetItem = style({
width: '100%',
fontSize: '1.4rem',
cursor: 'pointer',
padding: '2.5rem 2.8rem 2.5rem',

selectors: {
[`${sheetItemWrapper}:hover &`]: {
color: '#FF5454',
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { style } from '@vanilla-extract/css';

export const container = style({
width: '100%',

display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
});

export const shareAndOthers = style({
width: '100%',

display: 'flex',
flexDirection: 'row',
justifyContent: 'right',
alignItems: 'center',
gap: '20px',
});

export const buttonComponent = style({
cursor: 'pointer',
});
143 changes: 143 additions & 0 deletions src/app/[userNickname]/[listId]/_components/ListDetailInner/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
'use client';

import { useParams, useRouter } from 'next/navigation';
import { MouseEvent, useState } from 'react';
import BottomSheet from '@/app/[userNickname]/[listId]/_components/BottomSheet/BottomSheet';
import ModalPortal from '@/components/ModalPortal';
import saveImageFromHtml from '@/lib/utils/saveImageFromHtml';
import copyUrl from '@/lib/utils/copyUrl';
import toasting from '@/lib/utils/toasting';
import kakaotalkShare from '@/components/KakaotalkShare/kakaotalkShare';
import * as styles from './Footer.css';
import CollectIcon from '/public/icons/collect.svg';
import ShareIcon from '/public/icons/share.svg';
import EtcIcon from '/public/icons/etc.svg';

interface BottomSheetOptionsProps {
key: string;
title: string;
onClick: () => void;
}

interface SheetTypeProps {
type: 'share' | 'etc';
}

interface FooterProps {
category: string;
listId: string;
title: string;
description: string;
items: [];
collaborators: [];
ownerNickname: string;
}

function Footer({ data }: { data: FooterProps }) {
const router = useRouter();
const params = useParams<{ userNickname: string; listId: string }>();

const [isSheetActive, setSheetActive] = useState<boolean>(false);
const [sheetOptionList, setSheetOptionList] = useState<BottomSheetOptionsProps[]>([]);

const handleSheetOptionList = ({ type }: SheetTypeProps) => {
const listUrl = `${process.env.NEXT_PUBLIC_BASE_URL}/${params?.userNickname}/${params?.listId}`;

if (type === 'share') {
const optionList = [
{
key: 'copyLink',
title: '리스트 링크 복사하기',
onClick: () => {
copyUrl(listUrl);
setSheetActive(false);
},
},
{
key: 'kakaoShare',
title: '리스트 카카오톡으로 공유하기',
onClick: () => {
// TODO: image로 저장한다음에 해당 image를 보내줘야한다.
kakaotalkShare({
title: data.title,
description: data.description,
image:
'https://i.namu.wiki/i/-8Iah6PGZzzQuY1KtJIbj8_KBbX4whnbaq8AYShoqphdJOpfJDskZZ2Y3bU2I5Jpnx8aRi1LXTz1_e0v_fMrp172modjOmKRcxcME5dmM6IDAIgqktw5yIs75is2CgC1GrGoxZPwxpeTXudKIxWn2w.webp',
listItem: data.items,
collaborators: data.collaborators,
listId: data.listId,
userNickname: data.ownerNickname,
});
setSheetActive(false);
},
},
];
setSheetOptionList([...optionList]);
return;
}
Comment on lines +76 to +77
Copy link
Contributor

Choose a reason for hiding this comment

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

if문-fast 리턴 패턴 너무 편안하고 좋아요 ㅎㅎ


if (type === 'etc') {
const optionList = [
{
key: 'saveToImg',
title: '리스트 이미지로 저장하기',
onClick: () => {
setSheetActive(false);
saveImageFromHtml({ filename: `${data.category}_${data.listId}` });
},
},
{
key: 'copyAndCreateList',
title: '이 리스트 템플릿으로 바로 리스트 작성하기',
onClick: () => {
toasting({ type: 'default', txt: '리스트 작성 페이지로 이동합니다.' });
router.push(`/create?title=${data.title}&category=${data.category}`);
},
},
];
setSheetOptionList([...optionList]);
return;
}
};

const handleSheetActive = ({ type }: SheetTypeProps) => {
handleSheetOptionList({ type });
setSheetActive((prev: boolean) => !prev);
};

const handleOutsideClick = (e: MouseEvent) => {
if (e.target === e.currentTarget) {
setSheetActive(false);
}
};

// TODO: 콜렉트 API생성되면 요청보내고 UI변경시키기
const handleCollect = () => {
console.log('콜렉트기능 미구현');
};

return (
<>
{isSheetActive && (
<ModalPortal>
<BottomSheet onClose={handleOutsideClick} isActive={isSheetActive} optionList={sheetOptionList} />
</ModalPortal>
)}
<div className={styles.container}>
<div className={styles.buttonComponent}>
<CollectIcon onClick={handleCollect} />
</div>
<div className={styles.shareAndOthers}>
<div className={styles.buttonComponent} onClick={() => handleSheetActive({ type: 'share' })}>
<ShareIcon />
</div>
<div className={styles.buttonComponent} onClick={() => handleSheetActive({ type: 'etc' })}>
<EtcIcon />
</div>
</div>
</div>
</>
);
}

export default Footer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { style } from '@vanilla-extract/css';

export const container = style({
width: '100%',

display: 'flex',
justifyContent: 'right',
alignItems: 'center',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as styles from './Header.css';
import SelectComponent from '@/components/SelectComponent/SelectComponent';

interface OptionsProps {
value: string;
label: string;
}

interface HeaderProps {
handleChangeListType: (target: OptionsProps) => void | undefined;
}

const dropdownOptions = [
{
value: 'simple',
label: '간단히',
},
{
value: 'detail',
label: '자세히',
},
];
function Header({ handleChangeListType }: HeaderProps) {
return (
<div className={styles.container}>
<SelectComponent name="listType" options={dropdownOptions} isSearchable={false} onChange={handleChangeListType} />
</div>
);
}

export default Header;
Loading
Loading