Skip to content

Commit

Permalink
Merge pull request #125 from MeeTeamNumdle/release-1.0
Browse files Browse the repository at this point in the history
feat: 포트폴리오 관리 페이지 배포
  • Loading branch information
kimsuyeon0916 authored May 2, 2024
2 parents 99a3fcd + ee5f645 commit 67a622e
Show file tree
Hide file tree
Showing 15 changed files with 268 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ import ApplyRole from './recruit/role/ApplyRole';
import OpenChatModal from './recruit/applicants/modal/OpenChatModal';
import Toast from './recruit/applicants/toast/Toast';
import NeedLogin from './recruit/recruitDetail/modal/needLogin/NeedLogin';
import TabMenu from './tabMenu/TabMenu';

export {
Header,
Expand Down Expand Up @@ -281,4 +282,5 @@ export {
OpenChatModal,
Toast,
NeedLogin,
TabMenu,
};
2 changes: 1 addition & 1 deletion src/components/pagination/Pagination.styled.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from 'styled-components';

const Pagination = styled.article`
margin-top: 12rem;
margin: 12rem auto;
margin-bottom: 22rem;
button {
background-color: transparent;
Expand Down
46 changes: 46 additions & 0 deletions src/components/tabMenu/TabMenu.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import styled from 'styled-components';

const TabMenuLayout = styled.div`
display: flex;
flex-direction: row;
align-items: flex-end;
`;

const TabMenuList = styled.ul`
display: flex;
flex-direction: row;
color: var(--State-unactive, var(--, #8e8e8e));
/* Body/body1/medium */
font-size: 1.6rem;
font-weight: 500;
line-height: 1.9rem;
letter-spacing: 0.0032rem;
`;

const TabMenuItem = styled.li<{ $clicked?: boolean }>`
display: flex;
flex: 1;
justify-content: center;
align-items: center;
width: 11.6rem; // width: clamp(45%, 11.6rem, 75%);
height: 3.6rem;
border-radius: 0.4rem 0.4rem 0rem 0rem;
border: ${props => (props.$clicked ? '0.1rem solid #373f41' : '0.1rem solid #8E8E8E')};
border-bottom: ${props => (props.$clicked ? '0' : '0.1rem solid #373f41')};
background: ${props => !props.$clicked && '#F6F6F6'};
color: ${props => !props.$clicked && '#8E8E8E'};
cursor: pointer;
`;

const TabMenuLine = styled.hr`
all: unset;
display: flex;
height: 0.1rem;
background: #373f41;
width: 100%;
`;

const S = { TabMenuLayout, TabMenuList, TabMenuItem, TabMenuLine };

export default S;
33 changes: 33 additions & 0 deletions src/components/tabMenu/TabMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { useState } from 'react';
import S from './TabMenu.styled';

interface TabMenu {
readonly tabList: string[];
}

const TabMenu = ({ tabList }: TabMenu) => {
const [tab, setTab] = useState(tabList[0]);

const clickedHandler: React.MouseEventHandler<HTMLLIElement> = e => {
const tab = e.target as HTMLButtonElement;
if (!tab.textContent) {
throw new Error('No Content');
}
setTab(tab.textContent);
};

return (
<S.TabMenuLayout>
<S.TabMenuList>
{tabList.map((currentTab, index) => (
<S.TabMenuItem onClick={clickedHandler} $clicked={currentTab === tab} key={index}>
{currentTab}
</S.TabMenuItem>
))}
</S.TabMenuList>
<S.TabMenuLine />
</S.TabMenuLayout>
);
};

export default TabMenu;
8 changes: 5 additions & 3 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import useDebounce from './useDebounce';
import useValid from './useValid';
import { useReadSkillList, useReadRoleList } from './useSearch';
import {
useReadPortfolioList,
useReadPortfolio,
useCreatePortfolio,
useCreatePortfolio,
useUpdatePortfolio,
useReadInfinitePortfolioList,
usePaginationPortfolioList,
} from './usePortfolio';
import {
useReadImagePresignedUrl,
Expand All @@ -42,12 +43,13 @@ export {
useReadSkillList,
useReadRoleList,
useReadPortfolio,
useReadInfinitePortfolioList,
usePaginationPortfolioList,
useCreatePortfolio,
useUpdatePortfolio,
useReadImagePresignedUrl,
useReadImageListPresignedUrl,
useUploadImageFile,
useReadPortfolioList,
useIntersection,
useBookmark,
useLogin,
Expand Down
25 changes: 18 additions & 7 deletions src/hooks/usePortfolio.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useQuery, useMutation, useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
import { readPortfolioList, createPortfolio, readPortfolio, updatePortfolio } from '../service';
import { useQuery, useMutation, useInfiniteQuery, useQueryClient, keepPreviousData } from '@tanstack/react-query';
import { createPortfolio, readPortfolio, updatePortfolio, readInfinitePortfolioList, readPaginationPortfolioList } from '../service';

const portfolioKeys = {
readPortfolio: (portfolioId: string) => ['readPortfolio', portfolioId],
readPortfolioList: (size: number) => ['readProfile', size],
readInfinitePortfolioList: (size: number) => ['readInfinitePortfolioList', size],
readPaginationPortfolioList: (size: number) => ['readPaginationPortfolioList', size],
};

/**
Expand Down Expand Up @@ -55,11 +56,10 @@ export const useUpdatePortfolio = ({
/**
* @description 포트폴리오 목록 무한스크롤 조회 API를 호출하는 hook입니다.
*/

export const useReadPortfolioList = (size: number) => {
export const useReadInfinitePortfolioList = (size: number) => {
return useInfiniteQuery({
queryKey: portfolioKeys.readPortfolioList(size),
queryFn: ({ pageParam }) => readPortfolioList({ size, pageParam }),
queryKey: portfolioKeys.readInfinitePortfolioList(size),
queryFn: ({ pageParam }) => readInfinitePortfolioList({ size, pageParam }),
initialPageParam: 1,
getNextPageParam: lastPage => {
if (lastPage?.pageInfo.hasNextPage) {
Expand All @@ -68,3 +68,14 @@ export const useReadPortfolioList = (size: number) => {
},
});
};

/**
* @description 포트폴리오 목록 페이지네이션 조회 API를 호출하는 hook입니다.
*/
export const usePaginationPortfolioList = (size: number, pageParam: number) => {
return useQuery({
queryKey: portfolioKeys.readPaginationPortfolioList(size),
queryFn: () => readPaginationPortfolioList({ size, pageParam }),
placeholderData: keepPreviousData,
});
};
5 changes: 5 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
RecruitPostingApply,
RecruitMyPostings,
CompleteSignUpPage,
PortfolioManagementPage,
} from './pages/index.ts';
import './globalStyle.css';

Expand Down Expand Up @@ -103,6 +104,10 @@ const router = createBrowserRouter([
path: 'portfolio/edit/:portfolioId?',
element: <PortfolioEditPage />, // 생성 및 편집
},
{
path: 'portfolio/management',
element: <PortfolioManagementPage />,
}
],
},
]);
Expand Down
2 changes: 2 additions & 0 deletions src/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import RecruitPostingBookmark from './recruit/recruitManagePage/RecruitPostingBo
import RecruitPostingApply from './recruit/recruitManagePage/RecruitPostingApply';
import RecruitMyPostings from './recruit/recruitManagePage/RecruitMyPostings';
import CompleteSignUpPage from './account/complete/CompleteSignUpPage';
import PortfolioManagementPage from './portfolio/management/PortfolioManagmentPage';

export {
MainPage,
Expand Down Expand Up @@ -57,4 +58,5 @@ export {
RecruitPostingApply,
RecruitMyPostings,
CompleteSignUpPage,
PortfolioManagementPage,
};
72 changes: 72 additions & 0 deletions src/pages/portfolio/management/PortfolioManagementPage.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import styled from 'styled-components';

const PortfolioManagementLayout = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
margin: 0 auto;
// margin-bottom: 15rem;
width: clamp(45%, 96rem, 75%); // width: 96rem;
color: var(--Light-Black, #373f41);
h2 {
color: var(--Text-textColor1, #151515);
/* Headline/h2 */
font-size: 2.4rem;
font-weight: 700;
line-height: 2.9rem; /* 120.833% */
letter-spacing: 0.0048rem;
}
`;

const PortfolioManagementHeader = styled.header`
display: flex;
flex-direction: row;
margin-top: 8rem;
margin-bottom: 2rem;
`;

const PortfolioManagementGrid = styled.div`
display: grid;
// margin: 8rem 0;
margin-top: 8rem;
grid-template-columns: repeat(auto-fill, minmax(22.5rem, 1fr));
grid-auto-rows: minmax(12.7rem, auto);
row-gap: 4rem;
column-gap: 2rem;
/* 스크롤바 숨기기 */
overflow-y: auto;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
&::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera*/
`;

const PortfolioManagementColumn = styled.div`
position: fixed;
display: flex;
align-items: center;
justify-content: center;
left: 0;
top: 0;
width: 100%;
height: 100%;
color: var(--State-unactive, #8e8e8e);
/* Headline/h3 */
font-size: 2rem;
font-weight: 600;
line-height: 2.4rem; /* 120% */
letter-spacing: 0.004rem;
`;

const S = {
PortfolioManagementLayout,
PortfolioManagementHeader,
PortfolioManagementGrid,
PortfolioManagementColumn,
};

export default S;
48 changes: 48 additions & 0 deletions src/pages/portfolio/management/PortfolioManagmentPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useState } from 'react';
import S from './PortfolioManagementPage.styled';
import { Pagination, PortfolioCard, PrimaryBtn, TabMenu } from '../../../components';
import { useNavigate } from 'react-router-dom';
import { usePaginationPortfolioList } from '../../../hooks';

const tabList = ['전체'];

const PortfolioManagementPage = () => {
const navigate = useNavigate();

const [pageNumber, setPageNumber] = useState(1);
const { data: portfolioList, isSuccess } = usePaginationPortfolioList(16, pageNumber);

return (
isSuccess && (
<S.PortfolioManagementLayout>
<S.PortfolioManagementHeader>
<h2>포트폴리오</h2>
<PrimaryBtn
type='button'
title='포트폴리오 작성'
handleClick={() => navigate('/portfolio/edit')}
/>
</S.PortfolioManagementHeader>
<TabMenu tabList={tabList} />
{!portfolioList?.portfolios.length ? (
<S.PortfolioManagementGrid>
{portfolioList &&
portfolioList.portfolios?.map(portfolio => (
<PortfolioCard key={portfolio.id} {...portfolio} />
))}
</S.PortfolioManagementGrid>
) : (
<S.PortfolioManagementColumn>아직 작성한 포트폴리오가 없어요</S.PortfolioManagementColumn>
)}
<Pagination
postsNum={portfolioList?.pageInfo.totalContents as number}
postsPerPage={portfolioList?.pageInfo.size as number}
currentPage={pageNumber}
setCurrentPage={setPageNumber}
/>
</S.PortfolioManagementLayout>
)
);
};

export default PortfolioManagementPage;
4 changes: 2 additions & 2 deletions src/pages/profile/edit/ProfileEditPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
useReadImagePresignedUrl,
} from '../../../hooks';
import { useNavigate } from 'react-router-dom';
import { useReadPortfolioList } from '../../../hooks/usePortfolio';
import { useReadInfinitePortfolioList } from '../../../hooks/usePortfolio';

interface FormValues {
nickname?: string;
Expand Down Expand Up @@ -260,7 +260,7 @@ const ProfileEditPage = () => {
hasNextPage,
isFetching,
isSuccess: isPortfolioSuccess,
} = useReadPortfolioList(12);
} = useReadInfinitePortfolioList(12);
const portfolioList = useMemo(
() => (data ? data.pages.flatMap(response => response?.portfolios) : []),
[data]
Expand Down
1 change: 1 addition & 0 deletions src/service/endPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const EndPoint = {
/* portfolio */
PORTFOLIO: {
read: (portfolioId: string) => `/portfolio/${portfolioId}`,
readPortfolioList: '/portfolio',
create: '/portfolio',
update: (portfolioId: string) => `/portfolio/${portfolioId}`,
},
Expand Down
8 changes: 5 additions & 3 deletions src/service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import {
import { readProfile, updateProfile } from './user/Profile';
import { readSkillList, readRoleList } from './search/search';
import {
readPortfolioList,
readPortfolio,
createPortfolio,
createPortfolio,
updatePortfolio,
readInfinitePortfolioList,
readPaginationPortfolioList,
} from './portfolio/portfolio';
import { readImagePresignedUrl, readImageListPresignedUrl, uploadImageFile } from './image/image';
import {
Expand Down Expand Up @@ -55,10 +56,11 @@ export {
readPortfolio,
createPortfolio,
updatePortfolio,
readInfinitePortfolioList,
readPaginationPortfolioList,
readImagePresignedUrl,
readImageListPresignedUrl,
uploadImageFile,
readPortfolioList,
getPostingData,
getApplyData,
applyRole,
Expand Down
Loading

0 comments on commit 67a622e

Please sign in to comment.