diff --git a/src/api/idea.ts b/src/api/idea.ts
index 3172424..c3dd7e6 100644
--- a/src/api/idea.ts
+++ b/src/api/idea.ts
@@ -37,3 +37,18 @@ export const fetchIdeaSubjects = async () => {
const response = await instance.get('/api/v1/idea-subjects/briefs');
return response.data;
};
+
+// 아이디어 리스트 조회 API
+export const fetchIdeas = async (
+ page: number,
+ size: number,
+ generation: number,
+ subjectId?: number,
+ isActive?: boolean,
+ isBookmarked?: boolean,
+) => {
+ const response = await instance.get(
+ `/api/v1/users/ideas/overviews?page=${page}&size=${size}&generation=${generation}&subject-id=${subjectId}&is-active=${isActive}&is-bookmarked=${isBookmarked}`,
+ );
+ return response.data;
+};
diff --git a/src/components/hackathon/ideaDetail/ideaDetailInfo/TeamInfo.tsx b/src/components/hackathon/ideaDetail/ideaDetailInfo/TeamInfo.tsx
index 7d6d8f9..89dc711 100644
--- a/src/components/hackathon/ideaDetail/ideaDetailInfo/TeamInfo.tsx
+++ b/src/components/hackathon/ideaDetail/ideaDetailInfo/TeamInfo.tsx
@@ -28,8 +28,6 @@ interface TeamInfoProps {
}
export default function TeamInfo({ requirements }: TeamInfoProps) {
- // 목업 데이터
-
return (
diff --git a/src/components/hackathon/ideaList/filter/FilterDropdown.tsx b/src/components/hackathon/ideaList/filter/ActiveFilterDropdown.tsx
similarity index 55%
rename from src/components/hackathon/ideaList/filter/FilterDropdown.tsx
rename to src/components/hackathon/ideaList/filter/ActiveFilterDropdown.tsx
index 81428c0..736bb45 100644
--- a/src/components/hackathon/ideaList/filter/FilterDropdown.tsx
+++ b/src/components/hackathon/ideaList/filter/ActiveFilterDropdown.tsx
@@ -2,28 +2,35 @@ import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, Text } from '@goo
import { useState } from 'react';
import styles from './styles.module.scss';
-interface FilterDropDownProps {
- options: string[]; // 필터 옵션
- selectedValue: string; // 현재 선택된 값
- onChange: (value: string) => void;
+interface ActiveFilterDropdownProps {
+ options: { label: string; value: boolean | undefined }[];
+ selectedValue: boolean | undefined;
+ onChange: (value: boolean | undefined) => void;
disabled?: boolean;
}
-export default function FilterDropdown({ options, selectedValue, onChange, disabled = false }: FilterDropDownProps) {
+export default function ActiveFilterDropdown({
+ options,
+ selectedValue,
+ onChange,
+ disabled = false,
+}: ActiveFilterDropdownProps) {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => !disabled && setIsOpen(!isOpen);
+ const selectedLabel = options.find((option) => option.value === selectedValue)?.label || '전체';
+
return (
- {selectedValue || '전체'}
+ {selectedLabel}
- {options.map((option, index) => (
- onChange(option)}>
- {option}
+ {options.map((option) => (
+ onChange(option.value)}>
+ {option.label}
))}
diff --git a/src/components/hackathon/ideaList/filter/SubjectFilterDropdown.tsx b/src/components/hackathon/ideaList/filter/SubjectFilterDropdown.tsx
new file mode 100644
index 0000000..a56d3e5
--- /dev/null
+++ b/src/components/hackathon/ideaList/filter/SubjectFilterDropdown.tsx
@@ -0,0 +1,40 @@
+import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, Text } from '@goorm-dev/vapor-components';
+import { useState } from 'react';
+import styles from './styles.module.scss';
+
+interface SubjectFilterDropdownProps {
+ options: { id: number; name: string }[];
+ selectedValue: number;
+ onChange: (value: number) => void;
+ disabled?: boolean;
+}
+
+export default function SubjectFilterDropdown({
+ options,
+ selectedValue,
+ onChange,
+ disabled = false,
+}: SubjectFilterDropdownProps) {
+ const [isOpen, setIsOpen] = useState(false);
+ const toggle = () => !disabled && setIsOpen(!isOpen);
+
+ // 현재 선택된 주제의 이름 찾기 (id로 매칭)
+ const selectedTopicName = options.find((topic) => topic.id === selectedValue)?.name || '전체';
+
+ return (
+
+
+
+ {selectedTopicName}
+
+
+
+ {options.map((option) => (
+ onChange(option.id)}>
+ {option.name}
+
+ ))}
+
+
+ );
+}
diff --git a/src/pages/hackathon/IdeaList/IdeaList.tsx b/src/pages/hackathon/IdeaList/IdeaList.tsx
index a9111f7..6243a78 100644
--- a/src/pages/hackathon/IdeaList/IdeaList.tsx
+++ b/src/pages/hackathon/IdeaList/IdeaList.tsx
@@ -1,34 +1,73 @@
-import { BasicPagination, Button } from '@goorm-dev/vapor-components';
+import { BasicPagination, Button, Spinner } from '@goorm-dev/vapor-components';
import NoAccess from '../../../components/hackathon/ideaList/noAccess/NoAccess';
import styles from './styles.module.scss';
import { EditIcon } from '@goorm-dev/gds-icons';
import IdeaListItem from '../../../components/hackathon/ideaList/ideaItem/IdeaListItem';
-import { useState } from 'react';
-import FilterDropdown from '../../../components/hackathon/ideaList/filter/FilterDropdown';
-import mockIdeas from './mockIdea'; // 목업 데이터
-
-const isTeamBuilding = true;
-// 목업 데이터
+import { useEffect, useState } from 'react';
+import { fetchIdeas, fetchIdeaSubjects } from '../../../api/idea';
+import ActiveFilterDropdown from '../../../components/hackathon/ideaList/filter/ActiveFilterDropdown';
+import SubjectFilterDropdown from '../../../components/hackathon/ideaList/filter/SubjectFilterDropdown';
export default function IdeaList() {
- const hackathonTopics = ['전체', '해커톤 주제1', '해커톤 주제2', '해커톤 주제3'];
- const statusOptions = ['전체', '모집 중', '모집 완료'];
+ // 주제 가져오기
+ const [hackathonTopics, setHackathonTopics] = useState<{ id: number; name: string }[]>([]);
+ const [ideaList, setIdeaList] = useState(null);
+ const { ideas, page_info } = ideaList;
+ const [loading, setLoading] = useState(false);
+
+ // 필터링
+ const [selectedTopic, setSelectedTopic] = useState(0);
+ const [selectedStatus, setSelectedStatus] = useState(undefined);
const [currentPage, setCurrentPage] = useState(1);
- const [selectedTopic, setSelectedTopic] = useState('전체');
- const [selectedStatus, setSelectedStatus] = useState('모집 중');
+ const statusOptions = [
+ { label: '전체', value: undefined },
+ { label: '모집 중', value: true },
+ { label: '모집 완료', value: false },
+ ];
+
+ // 주제 가져오는 api
+ useEffect(() => {
+ const loadTopics = async () => {
+ try {
+ const response = await fetchIdeaSubjects();
+ const activeTopics = response.data.idea_subjects
+ .filter((topic: { is_active: boolean }) => topic.is_active)
+ .map((topic: { id: number; name: string }) => ({ id: topic.id, name: topic.name }));
+
+ setHackathonTopics([{ id: null, name: '전체' }, ...activeTopics]); // "전체" 옵션 추가
+ } catch (error) {
+ console.error('Error fetching idea subjects:', error);
+ }
+ };
+
+ loadTopics();
+ }, []);
+
+ // 아이디어 가져오는 api
+ useEffect(() => {
+ const loadIdeas = async () => {
+ setLoading(true);
+ try {
+ const subjectId = selectedTopic === 0 ? undefined : selectedTopic;
+ const isActive = selectedStatus === true ? undefined : selectedStatus === false;
+
+ const response = await fetchIdeas(currentPage, projectsPerPage, 4, subjectId, isActive);
+ setIdeaList(response.data);
+ } catch (error) {
+ console.error('Error fetching ideas:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
- const filteredIdeas = mockIdeas.filter((idea) => {
- return (
- (selectedTopic === '전체' || idea.topic === selectedTopic) &&
- (selectedStatus === '전체' || idea.status === selectedStatus)
- );
- });
+ loadIdeas();
+ }, [selectedTopic, selectedStatus, currentPage]);
+ // 팀빌딩 기간인지
+ const isTeamBuilding = true;
// 한 페이지당 보여질 페이지 수
const projectsPerPage = 8;
- // 전체 페이지 개수
- const pageLength = Math.ceil(filteredIdeas.length / projectsPerPage);
const handlePageChange = (page: number) => {
setCurrentPage(page);
@@ -38,52 +77,58 @@ export default function IdeaList() {
{/* 추후 이미지 */}
-
- {/* 필터링, 아이디어 등록 버튼 */}
-
-
-
-
-
-
+ {loading ? (
+
+
- {/* 팀 빌딩 기간인지에 따라 달라지는 모습 */}
- {isTeamBuilding ? (
-
- {filteredIdeas.map((idea) => (
-
+ {/* 필터링, 아이디어 등록 버튼 */}
+
+
+
- ))}
-
-
handlePageChange(currentPage)}
- className={styles.basicPagination}
- />
+ setSelectedStatus(value)}
+ disabled={!isTeamBuilding}
+ />
+
+
- ) : (
-
- )}
-
+ {/* 팀 빌딩 기간인지에 따라 달라지는 모습 */}
+ {isTeamBuilding ? (
+
+ {ideas?.map((idea: any) => (
+
+ ))}
+
+ handlePageChange(currentPage)}
+ className={styles.basicPagination}
+ />
+
+ ) : (
+
+ )}
+
+ )}
);
}