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

[WORK] 모바일 대응 및 디자인 수정 반영 #27

Merged
merged 17 commits into from
Oct 14, 2024
Merged
25 changes: 15 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,24 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

function App() {
const helmetContext = {};
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
throwOnError: true,
},
},
});

return (
<QueryClientProvider client={queryClient}>

<ReactQueryDevtools initialIsOpen={false} />
<HelmetProvider context={helmetContext}>
<ThemeProvider>
<Layout>
<Outlet />
</Layout>
</ThemeProvider>
</HelmetProvider>
<ReactQueryDevtools initialIsOpen={false} />
<HelmetProvider context={helmetContext}>
<ThemeProvider>
<Layout>
<Outlet />
</Layout>
</ThemeProvider>
</HelmetProvider>
</QueryClientProvider>
);
}
Expand Down
5 changes: 5 additions & 0 deletions src/assets/icons/left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions src/components/Layout/WorkDetailHeaderLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import WorkDetailHeader from '../../pages/Work/components/workDetail/WorkDetailHeader';

interface WorkDetailHeaderLayoutProps {
children: React.ReactNode;
}

const WorkDetailHeaderLayout = ({ children }: WorkDetailHeaderLayoutProps) => {
return (
<>
<WorkDetailHeader />
{children}
</>
);
};

export default WorkDetailHeaderLayout;
21 changes: 1 addition & 20 deletions src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,4 @@ export const WORDS = [
];

// CategoriesSection.tsx
export const CATEGORIES = ['ALL', 'UX', 'Brand', 'Graphic', 'Illust', 'Media'] as const;

// 임시로 추가. 서버 연결 후 삭제 예정.
export const MOCK_DATA = [
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
{ 학생이름: '이가영', 작품이름: '스윗', 이미지: '' },
];
export const CATEGORIES = ['ALL', 'UX', 'BRAND', 'GRAPHIC', 'ILLUST', 'MEDIA'] as const;
24 changes: 21 additions & 3 deletions src/hooks/queries/useGetWorkList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ export const useGetWorkList = ({ category, currentPage }: WorkListRequestType) =
queryKey: WORK_KEYS.list(category, currentPage),
queryFn: ({ pageParam = currentPage }) => getWorkList(category, pageParam),
getNextPageParam: (lastPage, allPages) => {
return lastPage.length === 10 ? allPages.length + 1 : null;
console.log('LASTPAGE', lastPage);
if (lastPage && Array.isArray(lastPage) && lastPage.length === 10) {
return allPages.length + 1;
}
return null;
},
initialPageParam: 1,
select: (data) => ({
pages: data?.pages.flatMap((page) => page),
pages: data?.pages.flatMap((page) => page) || [],
pageParams: data.pageParams,
}),
});
Expand All @@ -21,8 +25,22 @@ export const useGetWorkList = ({ category, currentPage }: WorkListRequestType) =
};

const getWorkList = async (category: string, currentPage: number) => {
const mappedCategory = (() => {
switch (category) {
case 'ILLUST':
return 'ILLUSTRATION';
case 'UX':
return 'UXUI';
case 'BRAND':
return 'BX';
default:
return category;
}
})();

const res = await get<WorkListResponseType>(
`work?category=${category}&currentPage=${currentPage}`
`work?category=${mappedCategory}&currentPage=${currentPage}`
);
console.log('API Response:', res);
return res.result.works as WorkListType[];
};
17 changes: 0 additions & 17 deletions src/pages/ErrorFallback.tsx

This file was deleted.

53 changes: 39 additions & 14 deletions src/pages/Work/Work.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,52 @@
import { Helmet } from 'react-helmet-async';
import CategoriesSection from './components/CategoriesSection';
import ExhibitionSection from './components/ExhibitionSection';
import CategoriesSection from './components/work/CategoriesSection';
import ExhibitionSection from './components/work/ExhibitionSection';
import styled from 'styled-components';
import { useGetWorkList } from '../../hooks/queries/useGetWorkList';
import { useState } from 'react';
import { Category } from '../../types/types';
import { useIsMobile } from '../../hooks/useIsMobile';
import MobileHeader from './components/mobile/MobileHeader';

function Work() {
const Work = () => {
const [category, setCategory] = useState<Category>('ALL');
const { data, hasNextPage, fetchNextPage, isFetchingNextPage } = useGetWorkList({
category,
currentPage: 1,
});
const isMobile = useIsMobile();

return (
<WorkPage>
<Helmet>
<title>Digging Club - Work</title>
</Helmet>
<div>
<CategoriesSection category={category} setCategory={setCategory} />
<ExhibitionSection
data={data}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={isFetchingNextPage}
/>
</div>
{isMobile ? (
<MobileDiv>
<MobileHeader category={category} setCategory={setCategory} />
<ExhibitionSection
data={data}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={isFetchingNextPage}
isMobile={isMobile}
/>
</MobileDiv>
) : (
<PcDiv>
<CategoriesSection category={category} setCategory={setCategory} />
<ExhibitionSection
data={data}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={isFetchingNextPage}
isMobile={isMobile}
/>
</PcDiv>
)}
</WorkPage>
);
}
};

export default Work;

Expand All @@ -38,6 +55,14 @@ const WorkPage = styled.div`

display: flex;
justify-content: center;
`;

const PcDiv = styled.div`
padding: 6rem 0 10.4rem 0;
`;

padding: 80px 0 104px 0;
const MobileDiv = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`;
50 changes: 30 additions & 20 deletions src/pages/Work/WorkDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import styled from 'styled-components';
import WorkInfoSection from './components/WorkInfoSection';
import WorkInfoSection from './components/workDetail/WorkInfoSection';
import YouTube from 'react-youtube';
import { useGetWorkDetail } from '../../hooks/queries/useGetWorkDetail';
import { useParams } from 'react-router-dom';
import { useIsMobile } from '../../hooks/useIsMobile';
import MobileWorkDetail from './components/mobile/MobileWorkDetail';

const WorkDetail = () => {
const params = useParams();
const name = params.name;
const title = params.title;

const isMobile = useIsMobile();

if (!name || !title) {
throw new Error('[에러 발생]작품명이나 작가 이름값이 존재하는지 확인하세요.');
}
Expand All @@ -18,23 +22,28 @@ const WorkDetail = () => {
if (!result) {
return <WorkDetailPage />;
}

return (
return isMobile ? (
<MobileWorkDetail />
) : (
<WorkDetailPage>
<WorkInfoSection data={result} />
<WorkDetailContent>
<YouTube
videoId={'RZ1E1itFAkE'}
opts={{
width: '1220',
height: '686',
playerVars: {
autoplay: 1,
rel: 0,
modestbranding: 1,
},
}}
/>
{result.videoUrl ? (
<YouTube
videoId={result.videoUrl.split('/').pop()}
opts={{
width: '950',
height: '534',
playerVars: {
autoplay: 1,
rel: 0,
modestbranding: 1,
},
}}
/>
) : (
<></>
)}
<WorkImg src={result.detailArtUrl || ''} alt={title || '작품-이미지'} />
</WorkDetailContent>
</WorkDetailPage>
Expand All @@ -44,23 +53,24 @@ const WorkDetail = () => {
export default WorkDetail;

const WorkDetailPage = styled.div`
padding-top: 80px;
padding-bottom: 104px;
margin-top: 6rem;
margin-bottom: 10.4rem;

display: flex;
justify-content: center;

column-gap: 40px;
column-gap: 4rem;
`;

const WorkDetailContent = styled.div`
margin-top: 3.3rem;
display: flex;
flex-direction: column;
`;

const WorkImg = styled.img`
width: 950px;
min-height: 838px;
width: 95rem;
min-height: 83.8rem;

object-fit: cover;
background-color: gray;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Suspense } from 'react';
import { QueryErrorResetBoundary } from '@tanstack/react-query';
import { ErrorBoundary } from 'react-error-boundary';
import DelayedComponent from '../pages/DelayedComponent';
import ErrorFallback from '../pages/ErrorFallback';
import ErrorFallback from './ErrorFallback';
import DelayedComponent from './DelayedComponent';


const DelayRouteWrapper = ({ children }: { children: React.ReactNode }) => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ const DelayedComponent = ({ children }: PropsWithChildren<{}>) => {
const [isDelayed, setIsDelayed] = useState(false);

useEffect(() => {
console.log('타이머 시작');
const timeoutId = setTimeout(() => {
setIsDelayed(true);
}, 2000);
}, 1000);
return () => clearTimeout(timeoutId);
}, []);

Expand Down
25 changes: 25 additions & 0 deletions src/pages/Work/components/error/ErrorBtn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from 'styled-components';

interface ErrorBtnProps {
onClick: VoidFunction;
text: string;
}
const ErrorBtn = ({ onClick, text }: ErrorBtnProps) => {
return <BtnWrapper onClick={onClick}>{text}</BtnWrapper>;
};

export default ErrorBtn;

const BtnWrapper = styled.div`
width: 10rem;
height: 3rem;

display: flex;
justify-content: center;
align-items: center;

font-size: 1.4rem;
border-radius: 1rem;
background-color: gray;
cursor: pointer;
`;
Loading
Loading