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] portfolio page 구현 #62

Merged
merged 32 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6b830a7
chore: sweetAlert2 설치
joarthvr Nov 27, 2024
1243075
feat: sweetAlert2 설정
joarthvr Nov 27, 2024
e3fce7f
style: sweetAlert 스타일 설정
joarthvr Nov 27, 2024
f9ba254
feat: WriteGatheringPage
joarthvr Nov 27, 2024
5c11a1f
fix: 스니펫 인터페이스 = 빼기
joarthvr Nov 27, 2024
5cba503
chore: 리액트 훅 폼 설치
joarthvr Nov 28, 2024
bdc1b78
feat: 게더링에서 사용될 옵션 타입 정의
joarthvr Nov 28, 2024
b96368e
feat: 게더링 셀렉트 버튼 구현
joarthvr Nov 28, 2024
e641a3c
feat: 게더링 deadline 옵션 구현
joarthvr Nov 28, 2024
5f3590d
feat: 게더링 링크 옵션 구현
joarthvr Nov 28, 2024
d5ca0a7
feat: 게더링 태그 옵션 구현
joarthvr Nov 28, 2024
6f7bafd
feat: 게더링 타이틀 옵션 구현
joarthvr Nov 28, 2024
b1a87e9
refactor: 게더링 옵션에 맞게 공유 컴포넌트 수정
joarthvr Nov 28, 2024
a8f3225
refactor: 게더링 옵션에 맞게 셀렉 위젯 수정
joarthvr Nov 28, 2024
ddc756a
feat: 게더링 마크다운 에디터 임시 컴포넌트 구현
joarthvr Nov 28, 2024
7318b4f
feat: 게더링 상단 옵션 위젯 구현
joarthvr Nov 28, 2024
9a2d949
feat: 게더링 하단 디테일 위젯 구현
joarthvr Nov 28, 2024
6c386b0
feat: 게더링 페이지 레이아웃 구현
joarthvr Nov 28, 2024
7c9f0bc
feat: 포트폴리오리스트 페이지 페이지 레이아웃 구현
joarthvr Nov 28, 2024
7258b51
rename 게더링 카드 컴포넌트 ->feature/gathering 이동
joarthvr Nov 28, 2024
ec72e3c
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
joarthvr Nov 28, 2024
ad61bd3
feat: portfolio card, gird 레이아웃 1
joarthvr Nov 28, 2024
b3d00b4
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
joarthvr Nov 28, 2024
59a83a0
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
joarthvr Nov 29, 2024
7116b1c
feat: 포트폴리오 카드 구현
joarthvr Nov 29, 2024
be2f07f
feature: widget 포트폴리오 그리드 위젝 구현
joarthvr Nov 29, 2024
6637768
feat: 포트폴리오 페이지 레이아웃 구현
joarthvr Nov 29, 2024
327c674
feat: 포트폴리오 관련 index 정리
joarthvr Nov 29, 2024
899c0e0
feat: 게더링 등록하기 버튼 추가
joarthvr Nov 29, 2024
461390a
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
joarthvr Nov 29, 2024
b01787c
fix: 배포 오류(import 오류) 수정
joarthvr Nov 29, 2024
e5a7806
fix: 서치탭 소모임 -> 게더링으로 수정
joarthvr Nov 29, 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
3 changes: 2 additions & 1 deletion src/app/appRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DetailArchivePage,
ArchiveListPage,
WriteGatheringPage,
PortfolioListPage,
WriteArchivePage,
RegisterPage,
SearchPage,
Expand All @@ -22,7 +23,7 @@ const AppRouter = () => {
},
{
path: '/portfolio',
element: <>{/** portfolioPage */}</>,
element: <PortfolioListPage />,
},
{
path: '/archive',
Expand Down
2 changes: 2 additions & 0 deletions src/features/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './archive';
export * from './gathering';
export * from './portfolio';
export * from './search';

2 changes: 2 additions & 0 deletions src/features/portfolio/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { PortfolioCard } from './ui/PortfolioCard';
export type { Portfolio } from './model/types';
9 changes: 9 additions & 0 deletions src/features/portfolio/model/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type Portfolio = {
portFolioId: number;
portFolioUrl: string;
username: string;
introduction: string;
majorJobGroup: string;
minorJobGroup: string;
memberImageUrl: string;
};
105 changes: 105 additions & 0 deletions src/features/portfolio/ui/PortfolioCard.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
.container {
width: 18rem;
height: 30.5625rem;
padding-top: 2rem;

// border: 1px solid $primary-color;
transition:
transform 0.3s ease,
box-shadow 0.3s ease; // 트랜지션 효과 추가

&:hover {
transform: translateY(-8px) scale(1.02); // 위로 떠오르면서 약간 확대
}
}

.card {
display: flex;
flex-direction: column;
gap: 1rem;
}

.cardHeader {
position: relative;
width: 18rem;
height: 18.75rem;
overflow: hidden;
}

.cardImg {
display: block;
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 12px;

img {
width: 100%;
height: 100%;
object-fit: cover;
background-color: #afafaf;
border-radius: 12px;
fill: $primary-color;
transition: transform 0.3s ease;
}
}

.contactBtn {
position: absolute;
top: 1rem;
right: 1rem;
padding: 0.5rem 1rem;
cursor: pointer;
background-color: white;
border: 1px solid $primary-color;
border-radius: 2rem;
}

.cardFooter {
display: flex;
flex-direction: column;
gap: 0.75rem;
padding: 0 0.5rem;
}

.firstInfo {
display: flex;
gap: 1rem;
align-items: center;
justify-content: space-between;
color: $primary-color;
}

.name {
font-size: 1.25rem;
font-weight: 600;
color: $primary-color;
}

.job {
display: flex;
gap: 0.5rem;
justify-content: space-between;
font-size: 1rem;
font-weight: 500;
color: $primary-color;
}

.introduction {
display: -webkit-box;
overflow: hidden;
font-size: 0.875rem;
font-weight: 400;
line-height: 1.5;
color: #afafaf;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
line-clamp: 3;
word-break: break-word;
-webkit-box-orient: vertical;
}

// hover 시 이미지만 확대하고 싶은 경우 추가
.container:hover .cardImg img {
transform: scale(1.05);
}
55 changes: 55 additions & 0 deletions src/features/portfolio/ui/PortfolioCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Link } from 'react-router-dom';

import styles from './PortfolioCard.module.scss';

import profileImg from '@/shared/assets/paletteLogo.svg';

interface PortfolioCardProps {
portFolioId: number;
portFolioUrl: string;
username: string;
introduction: string;
majorJobGroup: string;
minorJobGroup: string;
memberImageUrl: string;
}

export const PortfolioCard = ({
// portFolioId,
portFolioUrl,
username,
introduction,
majorJobGroup,
minorJobGroup,
memberImageUrl,
}: PortfolioCardProps) => {
return (
<div className={styles.container}>
<div className={styles.card}>
<div className={styles.cardHeader}>
<Link className={styles.cardImg} to={portFolioUrl}>
<img
alt={`${username}의 프로필 이미지`}
src={memberImageUrl || profileImg} // 이미지가 없을 경우 기본 이미지 사용
/>
</Link>
<button className={styles.contactBtn}>연락하기</button>
</div>
<div className={styles.cardFooter}>
<div className={styles.firstInfo}>
<span className={styles.name}>{username}</span>
<span className={styles.heart}>♥</span>
</div>
<div className={styles.job}>
<div>
<span>{minorJobGroup}</span>
<span>@{majorJobGroup}</span>
</div>
<div>대표 색</div>
</div>
<div className={styles.introduction}>{introduction}</div>
</div>
</div>
</div>
);
};
78 changes: 78 additions & 0 deletions src/pages/PortfolioListPage/PortfolioListPage.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.pageWrapper {
position: relative;
width: 100%;
max-width: 1640px;
min-height: 100vh;
padding: 0 1rem;
margin: 0 auto;
}

.h1 {
margin-top: 4rem;
margin-bottom: 2.5rem;
font-size: 1.875rem;
font-weight: 700;
color: $primary-color;
text-align: center;
}

.contentContainer {
position: sticky;
display: flex; // grid 대신 flex 사용
gap: 2rem;
overflow: auto;

@media screen and (width <= 1440px) {
gap: 2rem;
}

@media screen and (width <= 1200px) {
gap: 1.5rem;
}

@media screen and (width <= 830px) {
flex-direction: column;
gap: 1.5rem;
}
}

.sidebarWrapper {
flex-shrink: 0;
width: 250px;

@media screen and (width <= 1200px) {
width: 220px;
}

@media screen and (width <= 830px) {
width: 100%;
}
}

.sidebarContainer {
position: fixed;
top: 16.5rem;
width: inherit;
max-height: calc(100vh - 14.5rem);
overflow-y: auto;

@media screen and (width <= 830px) {
position: relative;
top: 0;
width: 100%;
max-height: none;
}
}

.mainContent {
flex: 1;
min-width: 0; // flex item 오버플로우 방지
}

.buttonWrapper {
display: flex;
align-items: center;
justify-content: space-between;
max-width: 1340px;
margin: 0 auto;
}
49 changes: 49 additions & 0 deletions src/pages/PortfolioListPage/PortfolioListPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';

import styles from './PortfolioListPage.module.scss';

import { JOB_CATEGORIES } from '@/shared/model';
import { SidebarFilter } from '@/shared/ui';
import { Button, SelectBtn } from '@/shared/ui';
import { PortFolioGrid } from '@/widgets';
export const PortfolioListPage = () => {
const navigate = useNavigate();
const [sort, setSort] = useState({ label: '최신순', value: 'latest' });
return (
<div className={styles.pageWrapper}>
<h1 className={styles.h1}>포트폴리오</h1>

<div className={styles.contentContainer}>
<div className={styles.sidebarWrapper}>
<aside className={styles.sidebarContainer}>
<SidebarFilter categories={JOB_CATEGORIES} />
</aside>
</div>
<div className={styles.mainContent}>
<div className={styles.buttonWrapper}>
<SelectBtn
isClearable={false}
onChange={newValue => {
setSort(newValue as { label: string; value: string });
}}
options={[
{ label: '최신순', value: 'latest' },
{ label: '인기순', value: 'popular' },
]}
value={sort}
/>
<Button
onClick={() => {
navigate('/');
}}
>
포트폴리오 등록하기
</Button>
</div>
<PortFolioGrid />
</div>
</div>
</div>
);
};
10 changes: 6 additions & 4 deletions src/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export * from './GatheringListPage';
export { WriteArchivePage } from './WriteArchivePage/WriteArchivePage';
export { ArchiveListPage } from './ArchiveListPage/ArchiveListPage';
export { DetailArchivePage } from './DetailArchivePage/DetailArchivePage';
export * from './GatheringListPage';
export { PortfolioListPage } from './PortfolioListPage/PortfolioListPage';
export { RegisterPage } from './RegisterPage/RegisterPage';
export { WriteGatheringPage } from './WriteGatheringPage/WriteGatheringPage';
export { SearchPage } from './SearchPage/SearchPage';
export { ArchiveListPage } from './ArchiveListPage/ArchiveListPage';
export { WriteArchivePage } from './WriteArchivePage/WriteArchivePage';
export { WriteGatheringPage } from './WriteGatheringPage/WriteGatheringPage';

1 change: 1 addition & 0 deletions src/shared/model/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {JOB_CATEGORIES} from './jobCategories'
4 changes: 2 additions & 2 deletions src/shared/ui/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export { Button } from './Button/Button';
export { Modal } from './Modal/Modal';
export { GatheringCard } from './GatheringCard/GatheringCard';
export { JobTag } from './GatheringCard/JobTag';
export { GatheringCard } from '../../features/gathering/ui/GatheringCard/GatheringCard';
export { JobTag } from '../../features/gathering/ui/GatheringCard/JobTag';
export { SelectBtn } from './SelectBtn/SelectBtn';
export { MarkdownEditor } from './MarkdownEditor/MarkdownEditor';
export { Input } from './Input/Input';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
.container {
display: flex;
gap: 9.38rem;
justify-content: center;
align-items: center;
justify-content: center;
width: 100%;
margin-bottom: 2rem;
padding: 1rem;
margin-right: 1rem;
margin-bottom: 2rem;
}
Loading