Skip to content
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
48 changes: 48 additions & 0 deletions src/api/rooms/getSearchRooms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { apiClient } from '../index';

export interface SearchRoomItem {
roomId: number;
bookImageUrl: string;
roomName: string;
memberCount: number;
recruitCount: number;
deadlineDate: string;
isPublic: boolean;
isFinalized?: boolean;
genre?: string;
}

export interface SearchRoomsResponse {
isSuccess: boolean;
code: number;
message: string;
data: {
roomList: SearchRoomItem[];
nextCursor: string | null;
isLast: boolean;
};
}

export const getSearchRooms = async (
keyword: string,
sort: 'deadline' | 'memberCount',
cursor?: string,
isFinalized: boolean = false,
category: string = '',
): Promise<SearchRoomsResponse> => {
try {
const params = new URLSearchParams();
params.append('keyword', keyword);
params.append('sort', sort);
params.append('isFinalized', String(isFinalized));
if (cursor) params.append('cursor', cursor);
if (category) params.append('category', category);

const url = `/rooms/search?${params.toString()}`;
const response = await apiClient.get<SearchRoomsResponse>(url);
return response.data;
} catch (error) {
console.error('방 검색 API 오류:', error);
throw error;
}
};
2 changes: 1 addition & 1 deletion src/components/group/CompletedGroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const CompletedGroupModal = ({ onClose }: CompletedGroupModalProps) => {
participants: room.memberCount,
maximumParticipants: room.recruitCount,
coverUrl: room.bookImageUrl,
deadLine: 0,
deadLine: '',
isOnGoing: false,
};
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/group/MyGroupBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface Group {
userName?: string;
progress?: number;
coverUrl: string;
deadLine?: number;
deadLine?: string;
genre?: string;
isOnGoing?: boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/group/MyGroupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const MyGroupModal = ({ onClose }: MyGroupModalProps) => {
participants: room.memberCount,
maximumParticipants: room.recruitCount,
coverUrl: room.bookImageUrl,
deadLine: 0,
deadLine: '',
genre: '',
isOnGoing: room.type === 'playing' || room.type === 'playingAndRecruiting',
};
Expand Down
212 changes: 97 additions & 115 deletions src/components/search/GroupSearchResult.tsx
Original file line number Diff line number Diff line change
@@ -1,139 +1,95 @@
import styled from '@emotion/styled';
import { useState } from 'react';
import type { Group } from '../group/MyGroupBox';
import { useMemo } from 'react';
import { GroupCard } from '../group/GroupCard';
import { colors, typography } from '@/styles/global/global';
import { Filter } from '../common/Filter';

const GENRE = ['문학', '과학·IT', '사회과학', '인문학', '예술'];
import type { SearchRoomItem } from '@/api/rooms/getSearchRooms';

const FILTER = ['마감임박순', '인기순'];
const CATEGORIES = ['문학', '과학·IT', '사회과학', '인문학', '예술'] as const;

interface Props {
rooms: SearchRoomItem[];
isLoading: boolean;
isLast: boolean;
onLoadMore: () => void;
error: string | null;
selectedFilter: string;
setSelectedFilter: (v: string) => void;
onChangeCategory: (category: string) => void;
currentCategory: string;
}

const mapToGroupCardModel = (r: SearchRoomItem) => ({
id: String(r.roomId),
title: r.roomName,
userName: '',
participants: r.memberCount,
maximumParticipants: r.recruitCount,
coverUrl: r.bookImageUrl,
deadLine: r.deadlineDate,
genre: r.genre ?? '',
isOnGoing: r.isPublic,
});

const dummyMyGroups: Group[] = [
{
id: '1',
title: '시집만 읽는 사람들 3월',
userName: 'hoho2',
participants: 15,
maximumParticipants: 30,
coverUrl:
'https://marketplace.canva.com/EAF9zlwqylI/1/0/1003w/canva-%EB%B2%A0%EC%9D%B4%EC%A7%80-%EC%A3%BC%ED%99%A9-%EA%B7%80%EC%97%BD%EA%B3%A0-%EB%AF%B8%EB%8B%88%EB%A9%80%ED%95%9C-%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8-e%EB%B6%81-%EC%9C%84%EB%A1%9C-%EC%A2%8B%EC%9D%80%EA%B8%80-%EC%B1%85%ED%91%9C%EC%A7%80-zrZ6hI8_IWo.jpg',
deadLine: 1,
genre: '문학',
isOnGoing: true,
},
{
id: '2',
title: '시집만 읽는 사람들 3월',
userName: 'hoho2',
participants: 15,
maximumParticipants: 30,
coverUrl:
'https://marketplace.canva.com/EAF9zlwqylI/1/0/1003w/canva-%EB%B2%A0%EC%9D%B4%EC%A7%80-%EC%A3%BC%ED%99%A9-%EA%B7%80%EC%97%BD%EA%B3%A0-%EB%AF%B8%EB%8B%88%EB%A9%80%ED%95%9C-%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8-e%EB%B6%81-%EC%9C%84%EB%A1%9C-%EC%A2%8B%EC%9D%80%EA%B8%80-%EC%B1%85%ED%91%9C%EC%A7%80-zrZ6hI8_IWo.jpg',
deadLine: 2,
genre: '문학',
isOnGoing: true,
},
{
id: '3',
title: '시집만 읽는 사람들 3월',
userName: 'hoho2',
participants: 15,
maximumParticipants: 30,
coverUrl:
'https://marketplace.canva.com/EAF9zlwqylI/1/0/1003w/canva-%EB%B2%A0%EC%9D%B4%EC%A7%80-%EC%A3%BC%ED%99%A9-%EA%B7%80%EC%97%BD%EA%B3%A0-%EB%AF%B8%EB%8B%88%EB%A9%80%ED%95%9C-%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8-e%EB%B6%81-%EC%9C%84%EB%A1%9C-%EC%A2%8B%EC%9D%80%EA%B8%80-%EC%B1%85%ED%91%9C%EC%A7%80-zrZ6hI8_IWo.jpg',
deadLine: 3,
genre: '문학',
isOnGoing: true,
},
{
id: '4',
title: '시집만 읽는 사람들 3월',
userName: 'hoho2',
participants: 15,
maximumParticipants: 30,
coverUrl:
'https://marketplace.canva.com/EAF9zlwqylI/1/0/1003w/canva-%EB%B2%A0%EC%9D%B4%EC%A7%80-%EC%A3%BC%ED%99%A9-%EA%B7%80%EC%97%BD%EA%B3%A0-%EB%AF%B8%EB%8B%88%EB%A9%80%ED%95%9C-%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8-e%EB%B6%81-%EC%9C%84%EB%A1%9C-%EC%A2%8B%EC%9D%80%EA%B8%80-%EC%B1%85%ED%91%9C%EC%A7%80-zrZ6hI8_IWo.jpg',
deadLine: 4,
genre: '문학',
isOnGoing: true,
},
{
id: '5',
title: '시집만 읽는 사람들 3월',
userName: 'hoho2',
participants: 15,
maximumParticipants: 30,
coverUrl:
'https://marketplace.canva.com/EAF9zlwqylI/1/0/1003w/canva-%EB%B2%A0%EC%9D%B4%EC%A7%80-%EC%A3%BC%ED%99%A9-%EA%B7%80%EC%97%BD%EA%B3%A0-%EB%AF%B8%EB%8B%88%EB%A9%80%ED%95%9C-%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8-e%EB%B6%81-%EC%9C%84%EB%A1%9C-%EC%A2%8B%EC%9D%80%EA%B8%80-%EC%B1%85%ED%91%9C%EC%A7%80-zrZ6hI8_IWo.jpg',
deadLine: 4,
genre: '과학·IT',
isOnGoing: false,
},
{
id: '6',
title: '시집만 읽는 사람들 3월',
userName: 'hoho2',
participants: 15,
maximumParticipants: 30,
coverUrl:
'https://marketplace.canva.com/EAF9zlwqylI/1/0/1003w/canva-%EB%B2%A0%EC%9D%B4%EC%A7%80-%EC%A3%BC%ED%99%A9-%EA%B7%80%EC%97%BD%EA%B3%A0-%EB%AF%B8%EB%8B%88%EB%A9%80%ED%95%9C-%EC%9D%BC%EB%9F%AC%EC%8A%A4%ED%8A%B8-e%EB%B6%81-%EC%9C%84%EB%A1%9C-%EC%A2%8B%EC%9D%80%EA%B8%80-%EC%B1%85%ED%91%9C%EC%A7%80-zrZ6hI8_IWo.jpg',
deadLine: 4,
genre: '과학·IT',
isOnGoing: false,
},
];

const GroupSearchResult = () => {
const [selected, setSelected] = useState<string>('');
const [showGroup] = useState<Group[]>(dummyMyGroups);
const [selectedFilter, setSelectedFilter] = useState<string>('마감임박순');

const handleSelectTab = (tab: string) => {
if (selected === tab) {
setSelected('');
} else setSelected(tab);
};

const isEmptyShowGroup = () => {
if (showGroup.length === 0) {
return true;
} else return false;
};
const GroupSearchResult = ({
rooms,
isLoading,
isLast,
onLoadMore,
error,
selectedFilter,
setSelectedFilter,
onChangeCategory,
currentCategory,
}: Props) => {
const mapped = useMemo(() => rooms.map(mapToGroupCardModel), [rooms]);
const isEmpty = !isLoading && mapped.length === 0;

return (
<>
<TabContainer>
{GENRE.map(tab => (
<Tab key={tab} selected={tab === selected} onClick={() => handleSelectTab(tab)}>
{tab}
</Tab>
))}
{CATEGORIES.map(tab => {
const selected = tab === currentCategory;
return (
<Tab
key={tab}
selected={selected}
onClick={() => onChangeCategory(selected ? '' : tab)}
aria-pressed={selected}
>
{tab}
</Tab>
);
})}
</TabContainer>
<GroupCardHeader>
<GroupNum>전체 {showGroup.length}</GroupNum>
<GroupNum>전체 {mapped.length}</GroupNum>
<Filter
filters={FILTER}
selectedFilter={selectedFilter}
setSelectedFilter={setSelectedFilter}
></Filter>
/>
</GroupCardHeader>
<Content>
{isEmptyShowGroup() ? (
{error && <ErrorText>{error}</ErrorText>}
{isEmpty ? (
<EmptyContent>
<EmptyMainText>해당하는 모임방이 없어요</EmptyMainText>
<EmptySubText>직접 모임방을 만들어보세요.</EmptySubText>
<EmptySubText>검색어를 바꿔보거나 직접 모임방을 만들어보세요.</EmptySubText>
</EmptyContent>
) : (
showGroup.map(group => (
<GroupCard
key={group.id}
group={group}
isOngoing={group.isOnGoing ? true : false}
type={'search'}
/>
mapped.map(group => (
<GroupCard key={group.id} group={group} isOngoing={group.isOnGoing} type="search" />
))
)}

<LoadMoreArea>
{isLoading && <LoadingText>불러오는 중...</LoadingText>}
{!isLoading && !isLast && mapped.length > 0 && (
<LoadMoreButton onClick={onLoadMore}>더 보기</LoadMoreButton>
)}
</LoadMoreArea>
</Content>
</>
);
Expand All @@ -146,7 +102,7 @@ const TabContainer = styled.div`
flex-wrap: wrap;
gap: 12px;
padding: 0 20px;
margin-bottom: 24px;
margin-bottom: 16px;
`;

const Tab = styled.button<{ selected?: boolean }>`
Expand Down Expand Up @@ -187,7 +143,7 @@ const GroupNum = styled.span`

const EmptyContent = styled.div`
display: flex;
height: 100vh;
height: 60vh;
flex-direction: column;
justify-content: center;
align-items: center;
Expand All @@ -199,12 +155,38 @@ const EmptyMainText = styled.p`
font-size: ${typography.fontSize.lg};
font-weight: ${typography.fontWeight.semibold};
text-align: center;
justify-self: center;
`;

const EmptySubText = styled.p`
color: ${colors.grey[100]};
font-size: ${typography.fontSize.sm};
font-weight: ${typography.fontWeight.regular};
text-align: center;
justify-self: center;
`;

const LoadMoreArea = styled.div`
display: flex;
justify-content: center;
padding: 12px 0 24px;
`;

const LoadMoreButton = styled.button`
padding: 10px 16px;
border: none;
border-radius: 8px;
background: var(--color-darkgrey-main);
color: #fff;
font-size: ${typography.fontSize.sm};
cursor: pointer;
`;

const LoadingText = styled.p`
color: ${colors.grey[100]};
font-size: ${typography.fontSize.sm};
`;

const ErrorText = styled.p`
color: #ff6b6b;
font-size: ${typography.fontSize.sm};
text-align: center;
`;
4 changes: 1 addition & 3 deletions src/pages/group/Group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ const convertRoomItemToGroup = (
participants: room.memberCount,
maximumParticipants: room.recruitCount,
coverUrl: room.bookImageUrl,
deadLine: Math.ceil(
(new Date(room.deadlineDate).getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24),
),
deadLine: room.deadlineDate,
genre: category,
});

Expand Down
2 changes: 1 addition & 1 deletion src/pages/groupDetail/GroupDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const GroupDetail = () => {
participants: room.memberCount,
maximumParticipants: room.recruitCount,
coverUrl: room.roomImageUrl,
deadLine: 0,
deadLine: '',
genre: '',
isOnGoing: true,
};
Expand Down
Loading