Skip to content

Commit

Permalink
refactor :: team index page
Browse files Browse the repository at this point in the history
  • Loading branch information
dutexion committed Aug 25, 2024
1 parent 6f3fa05 commit f4f11c9
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 80 deletions.
46 changes: 46 additions & 0 deletions src/components/Headless/Conditional.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { ReactElement } from 'react';
import { IChildren } from '@/utils/types/components/children';

interface ConditionalProps<T> {
data: T;
isLoading: boolean;
emptyFunction: (data: T) => boolean;
renderComponent: ReactElement;
loadingComponent: ReactElement;
emptyComponent: ReactElement;
}

export const Conditional = () => {
const Wrapper = <T,>({
data,
isLoading,
emptyFunction,
renderComponent,
loadingComponent,
emptyComponent,
}: ConditionalProps<T>) => {
if (isLoading) {
return loadingComponent;
}

if (emptyFunction(data)) {
return emptyComponent;
}

return renderComponent;
};

const Render: React.FC<IChildren> = ({ children }) => {
return <>{children}</>;
};

const Loading: React.FC<IChildren> = ({ children }) => {
return <>{children}</>;
};

const Empty: React.FC<IChildren> = ({ children }) => {
return <>{children}</>;
};

return { Wrapper, Render, Loading, Empty };
};
16 changes: 16 additions & 0 deletions src/components/Layouts/LimitBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IChildren } from '@/utils/types/components/children';
import styled from '@emotion/styled';

interface IProps extends IChildren {
height?: number;
}

export const LimitBox = ({ children, height }: IProps) => {
return <Wrapper height={height}>{children}</Wrapper>;
};

const Wrapper = styled.div<Pick<IProps, 'height'>>`
width: 100%;
max-width: 1120px;
${(props) => props.height && `height: ${props.height}px`};
`;
22 changes: 22 additions & 0 deletions src/components/Layouts/VStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { IChildren } from '@/utils/types/components/children';
import styled from '@emotion/styled';

interface IProps extends IChildren {
widthFit?: boolean;
gap?: number;
}

export const VStack = ({ children, widthFit = true, gap = 0 }: IProps) => (
<Wrapper widthFit={widthFit} gap={gap}>
{children}
</Wrapper>
);

const Wrapper = styled.div<Pick<IProps, 'widthFit' | 'gap'>>`
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
gap: ${({ gap }) => `${gap}px`};
width: ${({ widthFit }) => (widthFit ? '100%' : 'auto')};
`;
157 changes: 77 additions & 80 deletions src/pages/Team/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,73 +7,101 @@ import { SearchBar } from '@/components/common/SearchBar';
import { useNavigate } from 'react-router-dom';
import { TeamCheckType } from '@/utils/types/teamType';
import { useCustomQuery } from '@/hooks/useCustomQueries';
import { useState } from 'react';
import { useMemo, useState } from 'react';
import Skeleton from '@/components/common/Skeleton';
import { LimitBox } from '@/components/Layouts/LimitBox';
import { Text } from '@/components/Elements/Text';
import { VStack } from '@/components/Layouts/VStack';
import { Conditional } from '@/components/Headless/Conditional';

export const Team = () => {
const link = useNavigate();
const navigate = useNavigate();
const [selected, setSelected] = useState(0);
const [searchTerm, setSearchTerm] = useState('');

const { Wrapper: TeamListWrapper, Render, Loading, Empty } = Conditional();

const { data: teamList }: TeamCheckType = useCustomQuery({
queryKey: ['team-list'],
url: '/v1/team/my-team',
select: (res) => res?.data.team_list,
});

const count = Math.ceil(teamList?.length / 3) || 1;
const filteredTeamList = useMemo(() => {
if (!teamList) return [];
return teamList.filter((team) => team.team_name_ko.toLowerCase().includes(searchTerm.toLowerCase()));
}, [teamList, searchTerm]);

const count = Math.ceil(filteredTeamList.length / 3) || 1;

const handleSearch = (value: string) => {
setSearchTerm(value);
setSelected(0);
};

return (
<Wrapper>
<TitleContainer>
<Title></Title>
<Describtion>프로젝트를 개발하고 관리할 팀을 정의해보세요.</Describtion>
</TitleContainer>
<LimitBox>
<Text size={30} weight={600} color={theme.color.gray8}>
</Text>
<Text size={24} weight={100} color={theme.color.gray8}>
프로젝트를 개발하고 관리할 팀을 정의해보세요.
</Text>
</LimitBox>
<UtilContainer>
<SearchBar width={312} placeholder="팀 검색" />
<XButton
width={100}
height={50}
buttonStyle="solid"
onClick={() => {
link('/team/create');
}}
>
<SearchBar
width={312}
placeholder="팀 검색"
value={searchTerm}
onChange={(e) => handleSearch(e.target.value)}
/>
<XButton width={100} height={50} buttonStyle="solid" onClick={() => navigate('/team/create')}>
<Icon icon={'ic:round-plus'} width={20} height={20} />팀 등록
</XButton>
</UtilContainer>
<ContainerWrapper>
{teamList ? (
teamList?.length > 0 ? (
teamList?.slice(selected * 3, selected * 3 + 3).map((element: any, index: number) => (
<div
onClick={() => {
link(`/team/${element.team_id}/manage`);
}}
key={index}
style={{
cursor: 'pointer',
}}
>
<TeamContainer
name={element.team_name_ko}
admin={element.administrator_name}
deploy={element.deploy_list}
tag={element.team_type}
/>
</div>
))
) : (
<TipBox>아직 생성하거나 속한 팀이 없습니다!</TipBox>
)
) : (
<>
{Array.from({ length: 3 }).map((_, i) => {
return <Skeleton radius={6} height={134} key={i} />;
})}
</>
)}
</ContainerWrapper>
{teamList && (
<LimitBox height={500}>
<VStack gap={14}>
<TeamListWrapper
data={teamList}
emptyFunction={() => {
return filteredTeamList.length === 0;
}}
isLoading={teamList === undefined}
renderComponent={
<Render>
{filteredTeamList.slice(selected * 3, selected * 3 + 3).map((element: any, index: number) => (
<div
onClick={() => navigate(`/team/${element.team_id}/manage`)}
key={index}
style={{ cursor: 'pointer', width: '100%' }}
>
<TeamContainer
name={element.team_name_ko}
admin={element.administrator_name}
deploy={element.deploy_list}
tag={element.team_type}
/>
</div>
))}
</Render>
}
emptyComponent={
<Empty>
<TipBox>검색 결과가 없거나, 속한 팀이 없습니다!</TipBox>
</Empty>
}
loadingComponent={
<Loading>
{Array.from({ length: 3 }).map((_, i) => (
<Skeleton radius={6} height={134} key={i} />
))}
</Loading>
}
/>
</VStack>
</LimitBox>
{filteredTeamList.length > 0 && (
<PaginationContainer>
{Array.from(new Array(count).keys()).map((i) => (
<Pagination selected={i === selected} key={i} onClick={() => setSelected(i)}>
Expand Down Expand Up @@ -105,23 +133,6 @@ const Pagination = styled.span<{ selected: Boolean }>`
transition: 0.1s ease-in-out;
`;

const TitleContainer = styled.div`
width: 100%;
max-width: 1120px;
`;

const Title = styled.div`
font-size: 30px;
font-weight: 600;
color: #202020;
`;

const Describtion = styled.div`
font-size: 24px;
font-weight: 100;
color: #202020;
`;

const UtilContainer = styled.div`
width: 100%;
max-width: 1120px;
Expand All @@ -143,17 +154,3 @@ const TipBox = styled.div`
border-radius: 8px;
font-size: 20px;
`;

const ContainerWrapper = styled.div`
width: 100%;
max-width: 1120px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: start;
gap: 14px;
> div {
width: 100%;
}
`;
3 changes: 3 additions & 0 deletions src/utils/types/components/children.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IChildren {
children: React.ReactNode;
}

0 comments on commit f4f11c9

Please sign in to comment.