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

[SP2] 프로젝트 탭 디테일한 디자인 수정 #248

Merged
merged 4 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all 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: 1 addition & 1 deletion src/components/common/Select/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const SelectTrigger = styled.button<{
background-image: url(${arrowDown});
transform: ${({ isOpened }) => (isOpened ? 'rotate(180deg)' : 'none')};
}
@media (max-width: 765.9px) {
@media (max-width: 899px) {
padding: 8px 12px;
border-radius: 16px;
font-size: 13px;
Expand Down
4 changes: 3 additions & 1 deletion src/views/ProjectPage/ProjectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { css } from '@emotion/react';
import { useState } from 'react';
import PageLayout from '@src/components/common/PageLayout';
import Select from '@src/components/common/Select';
import { useIsMobile } from '@src/hooks/useDevice';
import {
activeProjectCategoryList,
activeProjectPlatformList,
Expand All @@ -19,6 +20,7 @@ function Projects() {
const [selectedPlatform, setPlatform] = useState<ProjectPlatformType>(ProjectPlatformType.ALL);

const state = useFetch(selectedCategory, selectedPlatform);
const isMobile = useIsMobile('899px');

return (
<PageLayout
Expand All @@ -31,7 +33,7 @@ function Projects() {
<S.ContentWrapper>
<RecentProjectList />
<S.Spacing />
<S.SectionTitle>SOPT에서 진행된 프로젝트 둘러보기</S.SectionTitle>
<S.SectionTitle>SOPT{!isMobile && '에서 진행된'} 프로젝트 둘러보기</S.SectionTitle>
Copy link
Member Author

Choose a reason for hiding this comment

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

const isMobile = useIsMobile('899px');

useIsMobile 훅을 사용하고 있는데 초기값이 false였다가 true로 변하면서 텍스트가 SOPT에서 진행된 프로젝트 둘러보기에서 SOPT 프로젝트 둘러보기로 변하게 됩니다. 변함없이 처음부터 SOPT 프로젝트 둘러보기로 나오게 할 좋은 방법이 뭐가 있을까요?

Copy link
Member

Choose a reason for hiding this comment

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

  1. '에서 진행된'을 하나의 스타일드 컴포넌트로 감싸서, 그 친구에게 반응형을 적용하는 (display: none 먹이기) 방법도 있을 것 같습니다!
  2. useIsMobile 훅에서 초기값을 지정할 수 있도록 훅을 수정합니다!

요 두 방법이 잇을 것 같아요~~

Copy link
Contributor

Choose a reason for hiding this comment

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

저는 서진이가 제안해준 2번 방법이 더 좋을 것 같아요!
다른 작업할때 말씀해주신 문제와 비슷한 문제를 겪을 가능성이 높아보여요~

Copy link
Member Author

Choose a reason for hiding this comment

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

2번에 대해서 좀 더 자세히 설명해주실 수 있나요? 초기값을 어떤식으로 지정하면 좋을까요?
모바일 사이즈일 경우에만 SOPT 프로젝트 둘러보기 타이틀이 나와야 해요!

<S.FilterWrapper>
<Select
options={activeProjectCategoryList}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useDeviceType, useIsDesktop, useIsMobile } from '@src/hooks/useDevice';
import { CarouselArrowType, CarouselOverflowType } from '@src/lib/types/universal';

export default function RecentProjectListCarousel({ children }: { children: JSX.Element[] }) {
const isDesktopSize = useIsDesktop('1239px');
const isMobileSize = useIsMobile('767px');
const isDesktopSize = useIsDesktop('1920px');
const isMobileSize = useIsMobile('899px');
const deviceType = useDeviceType();

const arrowType = deviceType === 'desktop' ? CarouselArrowType.External : CarouselArrowType.None;
Expand Down
12 changes: 6 additions & 6 deletions src/views/ProjectPage/components/RecentProjectList/Item/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const GridWrapper = styled.div`
padding: 24px;
margin-right: 20px;
/* 모바일 뷰 */
@media (max-width: 767px) {
@media (max-width: 899px) {
width: 325px;
grid-template-areas: 'img detail' 'footer footer';
grid-template-columns: 48px auto;
Expand All @@ -40,7 +40,7 @@ const ThumbnailImage = styled(Image)`
border-radius: 10px;

/* 모바일 뷰 */
@media (max-width: 767px) {
@media (max-width: 899px) {
width: 48px;
height: 48px;
}
Expand All @@ -62,7 +62,7 @@ const TextName = styled.div`
letter-spacing: -0.48px;

/* 모바일 뷰 */
@media (max-width: 767px) {
@media (max-width: 899px) {
font-size: 16px;
letter-spacing: -0.24px;
}
Expand All @@ -79,7 +79,7 @@ const TextSummary = styled.div`
letter-spacing: -0.21px;

/* 모바일 뷰 */
@media (max-width: 767px) {
@media (max-width: 899px) {
font-size: 13px;
font-weight: 400;
letter-spacing: -0.195px;
Expand All @@ -98,7 +98,7 @@ const Chip = styled.div`
letter-spacing: -0.18px;

/* 모바일 뷰 */
@media (max-width: 767px) {
@media (max-width: 899px) {
height: 26px;
padding: 5px 8px;
font-size: 11px;
Expand Down Expand Up @@ -152,7 +152,7 @@ const TryLink = styled.a`
}

/* 모바일 뷰 */
@media (max-width: 767px) {
@media (max-width: 899px) {
font-size: 14px;
letter-spacing: -0.21px;
border-radius: 13px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { track } from '@amplitude/analytics-browser';
import { useIsMobile } from '@src/hooks/useDevice';
import { useMediaQuery } from 'react-responsive';
import { ProjectType } from '@src/lib/types/project';
import * as S from './style';

export default function ProjectCard({ project }: { project: ProjectType }) {
const isMobile = useIsMobile('899px');
const isMobile = useMediaQuery({ query: '(max-width: 899px)' });

return (
<S.ProjectCard href={`/project/${project.id}`} onClick={() => track('click_project_detail')}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@ export default function ProjectCardList({ projectList }: ProjectCardList) {
const { data, isNextPage, ref } = useInfiniteScroll(projectList);

return (
<>
<S.ProjectFeed>
<S.CardList>
{data.map((project) => (
<ProjectCard key={project.id} project={project} />
))}
</S.CardList>
{isNextPage && (
<div ref={ref}>
<div>
<OvalSpinner />
</div>
</div>
<S.SpinnerWrapper ref={ref}>
<OvalSpinner />
</S.SpinnerWrapper>
)}
</>
</S.ProjectFeed>
);
}
12 changes: 12 additions & 0 deletions src/views/ProjectPage/components/project/ProjectCardList/style.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import styled from '@emotion/styled';

export const ProjectFeed = styled.div`
display: flex;
flex-direction: column;
gap: 50px;
`;

export const CardList = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1fr;
Expand All @@ -17,3 +23,9 @@ export const CardList = styled.div`
width: 100%;
}
`;

export const SpinnerWrapper = styled.div`
display: flex;
justify-content: center;
width: 100%;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as S from './style';

export default function ProjectCardSkeletonUI() {
const array = new Array(9).fill(0);

return (
<S.CardList>
{array.map((_, index) => (
<S.ProjectCard key={index}>
<S.ProjectThumbnail />
<S.ProjectContent>
<S.ProjectHeader>
<S.ProjectLogo />
<S.ProjectText>
<S.ProjectTitle />
<S.ProjectType />
</S.ProjectText>
</S.ProjectHeader>
<S.ProjectSummary />
</S.ProjectContent>
</S.ProjectCard>
))}
</S.CardList>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import styled from '@emotion/styled';
import { colors } from '@sopt-makers/colors';

export const CardList = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 50px 28px;
width: 1112px;

@media (max-width: 1279px) and (min-width: 900px) {
grid-template-columns: 1fr 1fr;
width: 732px;
}

@media (max-width: 899px) {
grid-template-columns: 1fr;
gap: 16px;
width: 100%;
}
`;

export const ProjectCard = styled.div`
display: flex;
flex-direction: column;
gap: 10px;

width: 352px;
height: 308px;
padding: 14px;
border: 1px solid ${colors.gray700};
border-radius: 20px;

@media (max-width: 899px) {
width: 100%;
height: 88px;
padding: 0 0 10px 0;
border: none;
border-bottom: 1px solid ${colors.gray900};
border-radius: 0;
}
`;

export const ProjectContent = styled.div`
display: flex;
flex-direction: column;
gap: 4px;

@media (max-width: 899px) {
gap: 12px;
}
`;

export const ProjectThumbnail = styled.div`
width: 324px;
height: 192px;
background-color: ${colors.gray800};
border-radius: 8px;

@media (max-width: 899px) {
display: none;
}
`;

export const ProjectLogo = styled.div`
width: 40px;
height: 40px;
background-color: ${colors.gray800};
border-radius: 8px;

@media (min-width: 900px) {
display: none;
}
`;

export const ProjectHeader = styled.div`
display: flex;
gap: 12px;
`;

export const ProjectText = styled.div`
display: flex;
align-items: center;
gap: 6px;
`;

export const ProjectTitle = styled.div`
width: 100px;
height: 28px;
background-color: ${colors.gray800};
border-radius: 8px;
`;

export const ProjectType = styled.div`
width: 39px;
height: 28px;
background-color: ${colors.gray800};
border-radius: 8px;
`;

export const ProjectSummary = styled.div`
width: 270px;
height: 22px;
background-color: ${colors.gray800};
border-radius: 8px;

@media (max-width: 899px) {
width: 40%;
}
`;
49 changes: 12 additions & 37 deletions src/views/ProjectPage/components/project/ProjectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { Condition } from '@src/components/common/Condition';
import { State } from '@src/hooks/useFetchBase/types';
import { ProjectCategoryType, ProjectType } from '@src/lib/types/project';
import ProjectCardList from '@src/views/ProjectPage/components/project/ProjectCardList';
import ProjectCardSkeletonUI from '@src/views/ProjectPage/components/project/ProjectCardSkeletonUI';
import ProjectCategoryDescription from '@src/views/ProjectPage/components/project/ProjectCategoryDescription';
import ProjectListCount from '@src/views/ProjectPage/components/project/ProjectListCount';
import { EmptyContent } from '../common/EmptyContent';
import styles from './project-list.module.scss';
import * as S from './style';

interface ProjectListProp {
Expand All @@ -15,24 +15,27 @@ interface ProjectListProp {

export function ProjectList({ selectedCategory, state }: ProjectListProp) {
return (
<div>
<>
{(() => {
switch (state._TAG) {
case 'IDLE':
case 'LOADING':
return (
<div>
<ProjectCategoryDescription selectedCategory={selectedCategory} />
{ProjectListSkeletonUI()}
</div>
<>
<S.ProjectListHeader selectedCategory={selectedCategory}>
<ProjectCategoryDescription selectedCategory={selectedCategory} />
<S.ProjectListCountSkeletonUI />
</S.ProjectListHeader>
<ProjectCardSkeletonUI />
</>
);
case 'ERROR':
return <p>ERROR</p>;
case 'OK': {
const { data: projectList } = state;
const listLength = projectList.length;
return (
<div>
<>
<Condition statement={listLength > 0}>
<S.ProjectListHeader selectedCategory={selectedCategory}>
<ProjectCategoryDescription selectedCategory={selectedCategory} />
Expand All @@ -44,39 +47,11 @@ export function ProjectList({ selectedCategory, state }: ProjectListProp) {
<ProjectCategoryDescription selectedCategory={selectedCategory} />
<EmptyContent />
</Condition>
</div>
</>
);
}
}
})()}
</div>
);
}

function ProjectListSkeletonUI() {
const array = new Array(9).fill(undefined);
return (
<section className={styles['card-list']}>
{array.map((_, index) => {
return <CardSkeletonUI key={index} />;
})}
</section>
);
}

function CardSkeletonUI() {
return (
<article className={styles['skeleton']}>
<div className={styles['thumbnail']} />
<div className={styles['type-list']}>
<div className={styles['type']} />
<div className={styles['type']} />
</div>
<div className={styles['description']}>
<div className={styles['long-line']} />
<div className={styles['long-line']} />
<div className={styles['short-line']} />
</div>
</article>
</>
);
}
Loading
Loading