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

[FE][Feature] api 응답 포맷에 맞게 코드 수정 #146

Merged
merged 1 commit into from
Apr 11, 2024
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
Binary file removed src/assets/GroupIcon.png
Binary file not shown.
Binary file modified src/assets/PersonalIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/TeamIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/Thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 29 additions & 9 deletions src/components/RetroList/ContentsFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { useEffect, useRef } from 'react';
import { useState, useEffect, useRef } from 'react';
import * as S from '@/styles/RetroList/ContentsFilter.style';

type ContentsFilterProps = {
status: string;
onStatusChange: (newStatus: string) => void;
onFilter: (filterType: string) => void;
};

const ContentsFilter: React.FC<ContentsFilterProps> = ({ status, onStatusChange }) => {
const ContentsFilter: React.FC<ContentsFilterProps> = ({ onFilter }) => {
const [activeFilter, setActiveFilter] = useState<string>('ALL');
const [isActive, setIsActive] = useState<boolean>(false);
const handleActive = () => {
setIsActive(!isActive);
};

const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
Expand All @@ -23,17 +28,32 @@ const ContentsFilter: React.FC<ContentsFilterProps> = ({ status, onStatusChange
return (
<div ref={ref}>
<S.ContentsFilterButton
onClick={() => onStatusChange('All files')}
className={status === 'All files' ? 'active' : ''}
onClick={() => {
onFilter('ALL');
setActiveFilter('ALL');
handleActive();
}}
className={activeFilter === 'ALL' ? 'active' : ''}
>
ALL files
</S.ContentsFilterButton>
<S.ContentsFilterButton onClick={() => onStatusChange('Teams')} className={status === 'Teams' ? 'active' : ''}>
<S.ContentsFilterButton
onClick={() => {
onFilter('Teams');
setActiveFilter('Teams');
handleActive();
}}
className={activeFilter === 'Teams' ? 'active' : ''}
>
Teams
</S.ContentsFilterButton>
<S.ContentsFilterButton
onClick={() => onStatusChange('Personal')}
className={status === 'Personal' ? 'active' : ''}
onClick={() => {
onFilter('Personal');
setActiveFilter('Personal');
handleActive();
}}
className={activeFilter === 'Personal' ? 'active' : ''}
>
Personal
</S.ContentsFilterButton>
Expand Down
102 changes: 62 additions & 40 deletions src/components/RetroList/ContentsList.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
import React, { useState } from 'react';
import { useState } from 'react';
import BookmarkIcon_N from '@/assets/BookmarkIcon_N.png';
import BookmarkIcon_Y from '@/assets/BookmarkIcon_Y.png';
import LinkIcon from '@/assets/Link.png';
import MoreIcon from '@/assets/MoreIcon.png';
import PersonalIcon from '@/assets/PersonalIcon.png';
import ProgressBefore from '@/assets/Progress_Before.png';
import ProgressDone from '@/assets/Progress_Done.png';
import ProgressIng from '@/assets/Progress_Ing.png';
import TeamIcon from '@/assets/TeamIcon.png';
import Thumbnail from '@/assets/Thumbnail.png';
import Modal from '@/components/RetroList/Modal';
import * as S from '@/styles/RetroList/ContentsList.styles';

interface Content {
id: number;
title: string;
status: string;
userId: number | null;
userId: number;
teamId: number | null;
templateId: number;
status: string;
isBookmarked: boolean;
thumbnail: string;
startDate: string;
createdDate: string;
updatedDate: string;
}

interface ContentListProps {
status: string;
data: Content[];
viewMode: string;
searchData: string;
}

const ContentList: React.FC<ContentListProps> = ({ status, viewMode, searchData }) => {
const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData }) => {
const [openModalId, setOpenModalId] = useState<number | null>(null);

const openModalForItem = (itemId: number) => {
Expand All @@ -32,54 +42,55 @@ const ContentList: React.FC<ContentListProps> = ({ status, viewMode, searchData
setOpenModalId(null);
};

const data: Content[] = [
{ id: 1, title: '회고1', status: 'Teams', userId: null, teamId: 1 },
{ id: 2, title: '회고2', status: 'Teams', userId: null, teamId: 2 },
{ id: 3, title: '회고3', status: 'Teams', userId: null, teamId: 3 },
{ id: 4, title: '회고4', status: 'Teams', userId: null, teamId: 4 },
{ id: 5, title: '회고5', status: 'Personal', userId: 1, teamId: null },
{ id: 6, title: '회고6', status: 'Personal', userId: 2, teamId: null },
{ id: 7, title: '회고7', status: 'Personal', userId: 3, teamId: null },
{ id: 8, title: '회고8', status: 'Personal', userId: 4, teamId: null },
{ id: 9, title: '회고9', status: 'Personal', userId: 5, teamId: null },
{ id: 10, title: '회고10', status: 'Personal', userId: 5, teamId: null },
{ id: 11, title: '회고11', status: 'All files', userId: 5, teamId: null },
];

const filteredData = data.filter(
item => item.status === status && item.title.toLowerCase().includes(searchData.toLowerCase()),
);

const isBookmarked: boolean = true;
const filteredData = data.filter(item => item.title.toLowerCase().includes(searchData.toLowerCase()));

return (
<div>
{viewMode === 'board' && (
<S.Container>
<S.BoardContainer>
{filteredData.map(item => (
<S.Box key={item.id}>
<S.ImgBox>
<S.Thumbnail src={Thumbnail} />
<S.Thumbnail src={item.thumbnail ? item.thumbnail : Thumbnail} />
</S.ImgBox>
<hr />
<S.InfoBox>
{item.title}
<S.MoreIcon src={MoreIcon} onClick={() => openModalForItem(item.id)} />
<div style={{ display: 'flex', alignItems: 'center' }}>
<S.TeamIcon src={item.teamId ? TeamIcon : PersonalIcon} />
<S.RetroTitle>{item.title}</S.RetroTitle>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<S.BookmarkIcon src={item.isBookmarked ? BookmarkIcon_Y : BookmarkIcon_N} /> {/* 북마크 patch */}
<S.MoreIcon src={MoreIcon} onClick={() => openModalForItem(item.id)} />
</div>
<S.RetroUser>{item.userId}</S.RetroUser>
<div></div>
<S.RetroDate> {item.createdDate} 수정</S.RetroDate>
{/* 수정하면 수정 시각으로 변경*/}
<S.ProgressIcon
src={
item.status === 'NOT_STARTED'
? ProgressBefore
: item.status === 'IN_PROGRESS'
? ProgressIng
: ProgressDone
}
/>
<Modal onClose={closeModalForItem} isOpen={openModalId === item.id} />
</S.InfoBox>
</S.Box>
))}
</S.Container>
</S.BoardContainer>
)}

{viewMode === 'list' && (
<>
<S.ListContainer>
<S.ListTopBox>
<S.ListTitleBox>회고이름</S.ListTitleBox> <S.ListUserBox>생성자</S.ListUserBox>{' '}
<S.ListTimeBox>마지막 수정시간</S.ListTimeBox> <S.ListBookmarkBox>즐겨찾기</S.ListBookmarkBox>{' '}
<S.ListLinkBox>공유링크</S.ListLinkBox>
<S.ListProgressBox> 회고진행여부</S.ListProgressBox>
<S.ListTitleBox>회고이름</S.ListTitleBox> <S.ListUserBox>생성자</S.ListUserBox>
<S.ListTimeBox>마지막 수정시간</S.ListTimeBox> <S.ListBookmarkBox>즐겨찾기</S.ListBookmarkBox>
<S.ListLinkBox>회고 진행 여부</S.ListLinkBox>
<S.ListProgressBox>회고 수정</S.ListProgressBox>
</S.ListTopBox>

<div>
Expand All @@ -90,15 +101,26 @@ const ContentList: React.FC<ContentListProps> = ({ status, viewMode, searchData
<text></text> {/* 생성자 이름 */}
</S.ListUserBox>
<S.ListTimeBox>
<text> </text> {/* 수정시간 */}
{item.createdDate} {/* 수정하면 수정 시각으로 변경*/}
</S.ListTimeBox>
<S.ListBookmarkBox>{isBookmarked && <S.Icon src={BookmarkIcon_Y} />}</S.ListBookmarkBox>
<S.ListLinkBox>
<S.Icon src={LinkIcon} />
</S.ListLinkBox>
<S.ListBookmarkBox>
<S.Icon src={item.isBookmarked ? BookmarkIcon_Y : BookmarkIcon_N} />
</S.ListBookmarkBox>
<S.ListProgressBox>
<S.Icon src={ProgressBefore} />
<S.Icon
src={
item.status === 'NOT_STARTED'
? ProgressBefore
: item.status === 'IN_PROGRESS'
? ProgressIng
: ProgressDone
}
/>
</S.ListProgressBox>
<S.ListLinkBox>
<S.MoreIconListView src={MoreIcon} onClick={() => openModalForItem(item.id)} />
<Modal onClose={closeModalForItem} isOpen={openModalId === item.id} />
</S.ListLinkBox>
</S.ItemBox>
))}
</div>
Expand Down
126 changes: 121 additions & 5 deletions src/pages/RetroListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,129 @@ import Search from '@/components/RetroList/Search';
import ViewButton from '@/components/RetroList/ViewButton';
import * as S from '@/styles/RetroList/RetroListPage.style';

// 예시 데이터
const dummy = {
code: 200,
message: null,
data: {
totalCount: 5,
nodes: [
{
id: 1,
title: 'Sample Title 1',
userId: 100,
teamId: 200, // team
templateId: 0,
status: 'NOT_STARTED',
isBookmarked: false,
thumbnail: '',
startDate: '2024-04-10T09:22:51.538Z',
createdDate: '2024-04-10T09:22:51.538Z',
updatedDate: '2024-04-10T09:22:51.538Z',
},
{
id: 2,
title: 'Sample Title 2',
userId: 101,
teamId: 300, // team
templateId: 0,
status: 'NOT_STARTED',
isBookmarked: true,
thumbnail: '',
startDate: '2024-04-11T09:22:51.538Z',
createdDate: '2024-04-11T09:22:51.538Z',
updatedDate: '2024-04-11T09:22:51.538Z',
},
{
id: 3,
title: 'Sample Title 3',
userId: 102,
teamId: 400, // team
templateId: 0,
status: 'IN_PROGRESS',
isBookmarked: false,
thumbnail: 'https://example.com/thumbnail3.jpg',
startDate: '2024-04-12T09:22:51.538Z',
createdDate: '2024-04-12T09:22:51.538Z',
updatedDate: '2024-04-12T09:22:51.538Z',
},
{
id: 4,
title: 'Sample Title 4',
userId: 103,
teamId: null, // personal
templateId: 0,
status: 'IN_PROGRESS',
isBookmarked: true,
thumbnail: 'https://example.com/thumbnail4.jpg',
startDate: '2024-04-13T09:22:51.538Z',
createdDate: '2024-04-13T09:22:51.538Z',
updatedDate: '2024-04-13T09:22:51.538Z',
},
{
id: 5,
title: 'Sample Title 5',
userId: 104,
teamId: null, // personal
templateId: 0,
status: 'COMPLETED',
isBookmarked: false,
thumbnail: 'https://example.com/thumbnail5.jpg',
startDate: '2024-04-14T09:22:51.538Z',
createdDate: '2024-04-14T09:22:51.538Z',
updatedDate: '2024-04-14T09:22:51.538Z',
},
],
},
};

const formatDate = (isoDateString: string) => {
const date = new Date(isoDateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');

return `${year}-${month}-${day} ${hours}:${minutes}`;
};

const RetroListPage = () => {
const [status, setStatus] = useState<string>('All files');
// data 부분만 가져오기
const { nodes } = dummy.data;

const rawData = nodes.map(item => ({
id: item.id,
title: item.title,
userId: item.userId,
teamId: item.teamId,
templateId: item.templateId,
status: item.status,
isBookmarked: item.isBookmarked,
thumbnail: item.thumbnail,
startDate: formatDate(item.startDate),
createdDate: formatDate(item.createdDate),
updatedDate: formatDate(item.updatedDate),
}));

// useEffect(() => {
// fetch(''); // url
// });

const [retroData, setRetroData] = useState(rawData);
const [viewMode, setViewMode] = useState<string>('board');
const [searchData, setSearchData] = useState('');

const handleStatusChange = (newStatus: string) => {
setStatus(newStatus);
const handleContentsFilter = (filterType: string) => {
if (filterType === 'Personal') {
const filtered = rawData.filter(item => item.teamId === null);
setRetroData(filtered);
} else if (filterType === 'Teams') {
const filtered = rawData.filter(item => item.teamId !== null);
setRetroData(filtered);
} else if (filterType === 'ALL') {
setRetroData(rawData);
}
};

const handleViewModeChange = (newStatus: string) => {
Expand All @@ -27,7 +143,7 @@ const RetroListPage = () => {
<div>
<S.Container>
<S.FilterContainer>
<ContentsFilter status={status} onStatusChange={handleStatusChange} />
<ContentsFilter onFilter={handleContentsFilter} />
</S.FilterContainer>
<S.SearchContainer>
<Search onSearch={handleSearch} />
Expand All @@ -38,7 +154,7 @@ const RetroListPage = () => {
</S.Container>
<ControlBar />
<S.Box>
<ContentList status={status} viewMode={viewMode} searchData={searchData} />
<ContentList data={retroData} viewMode={viewMode} searchData={searchData} />
</S.Box>
</div>
</>
Expand Down
Loading
Loading