diff --git a/src/assets/img/gallery/banner_gallery.png b/src/assets/img/gallery/banner_gallery.png new file mode 100644 index 0000000..7443bf8 Binary files /dev/null and b/src/assets/img/gallery/banner_gallery.png differ diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index b4e8df2..4d28d35 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -31,6 +31,11 @@ const menuItems = [ hasDropdown: false, path: "/coc", }, + { + label: "GALLERY", + hasDropdown: false, + path: "/gallery", + } /* { label: "NEWS", hasDropdown: false }, { label: "SUPPORT", hasDropdown: false }, { label: "COC", hasDropdown: false },*/ diff --git a/src/components/Layout/Layout.tsx b/src/components/Layout/Layout.tsx index 79c62b6..46b0dbd 100644 --- a/src/components/Layout/Layout.tsx +++ b/src/components/Layout/Layout.tsx @@ -5,7 +5,12 @@ import Footer from "@/components/Footer/Footer.tsx"; const Layout = () => { const location = useLocation(); const isYellow = (): boolean => { - return location.pathname === "/about" || location.pathname === "/about/md"; + return ( + location.pathname === "/about" || + location.pathname === "/about/md" || + location.pathname === "/coc" || + location.pathname === "/gallery" + ); }; return (
diff --git a/src/pages/gallery/$id.tsx b/src/pages/gallery/$id.tsx new file mode 100644 index 0000000..cf8cc58 --- /dev/null +++ b/src/pages/gallery/$id.tsx @@ -0,0 +1,51 @@ +import * as React from "react"; +import { Container } from "@/components/Container"; +import { useGetNotice } from "@/quries/useGetNotice.ts"; +import { useNavigate, useParams } from "react-router-dom"; + +export const NoticeDetail: React.FC = () => { + const { id } = useParams(); + const nav = useNavigate(); + const { data } = useGetNotice(id); + + const goToList = () => { + nav("/board/notice"); + }; + + const notice = data?.data ?? undefined; + + return ( + notice && ( + +

공지사항

+
+
+
+

+ {notice.title} +

+

+ {new Date(notice.created_at).toLocaleDateString()} +

+ {/* REVIEW: 해시태그 컴포넌트는 없나? todo: hashtag*/} + {/*
#컨퍼런스
*/} +
+
+

+

+
+
+
+ +
+
+ ) + ); +}; + +export default NoticeDetail; diff --git a/src/pages/gallery/index.tsx b/src/pages/gallery/index.tsx new file mode 100644 index 0000000..e28dcc7 --- /dev/null +++ b/src/pages/gallery/index.tsx @@ -0,0 +1,136 @@ + +import BgImg from "@/assets/img/gallery/banner_gallery.png"; + +import { HeaderBanner } from "@/components/HeaderBanner"; +import { Breadcrumb } from "@/components/Breadcrumb"; +import { AboutSection, AboutSectionTitle } from "@/components/AboutSection"; + +import { SelectBox } from "@/components/SelectBox"; +import { useEffect, useState } from "react"; +import { Gallery, SelectValue } from "@/types/common.ts"; +import { useGetGallery } from "@/quries/useGetGallery"; +import { Pagination } from "@/components/Pagination"; + +const selectedOptions = [ + { label: "2024년", value: "2024" }, + { label: "2025년", value: "2025" }, +]; + + +const ActivityGallery = () => { + const [yearList, setYearList] = useState([]); + const [selectedYear, setSelectedYear] = useState(2025); + const [page, setPage] = useState(1); + + const { data } = useGetGallery(page); + + const galleryData: Gallery[] = data?.data ?? []; + const pagination = data?.pagination; + + useEffect(() => { + setYearList( + selectedOptions.map( + (option) => + ({ + ...option, + checked: option.value === String(selectedYear), + }) as SelectValue, + ), + ); + }, []); + + const onPageChange = (val: number) => { + setPage(val); + }; + + const onSelectYear = (value: string) => { + setSelectedYear(Number(value)); + setYearList( + selectedOptions.map( + (option) => + ({ ...option, checked: option.value === value }) as SelectValue, + ), + ); + }; + + return ( +
+ 온오프라인에서 학습하고 파이썬 기술과 트렌드를 공유하며, 다양한 외부 협업도 진행합니다. 헬로파이의 다양한 활동을 확인해보세요!`} + > + Home, + GALLERY + ]} + /> + + + +
+
+ HelloPY COC(Code of Conduct) +
+
+ HelloPY 활동 가이드 +
+
+ 신규 멤버는 자기소개, 기사 공유, 모각작 참여 등 기본 활동을 수행해야 합니다.
각 게시판에 정보를 공유하고 질문하거나 성과를 기록할 수 있으며, 활동량에 따라 등급이 상승합니다.
등급은 레몬파이부터 블루베리파이까지 나뉘며 오프라인 모임 또는 컨퍼런스 발표를 통해 추가 승급이 가능합니다. +
+
+
+ +
+ + + +
+ + + + + +
+
+ {galleryData + .filter((item) => item.title?.includes(String(selectedYear))) + .map((item, index) => ( +
+ {`gallery-${item.id}`} +
+
+ {item.title} +
+
+
+
+ ))} + + {galleryData && galleryData.length > 0 && pagination !== null && ( + + )} +
+
+ +
+ ); +}; + +export default ActivityGallery; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index e7769b0..7288883 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -66,7 +66,7 @@ export const Home = () => { `} buttonText="전체 활동 보기 →" textPosition="right" - buttonUrl="none" + buttonUrl="/gallery" /> { + return useQuery({ + queryKey: [GalleryService.QueryKey.getGallery, page], + queryFn: () => GalleryService.getGallery(page), + }); +}; diff --git a/src/quries/useGetNotice.ts b/src/quries/useGetNotice.ts index abaf32c..6063d5c 100644 --- a/src/quries/useGetNotice.ts +++ b/src/quries/useGetNotice.ts @@ -8,3 +8,5 @@ export const useGetNotice = (id?: string) => { enabled: !!id, }); }; + + diff --git a/src/service/galleryService.ts b/src/service/galleryService.ts new file mode 100644 index 0000000..b548336 --- /dev/null +++ b/src/service/galleryService.ts @@ -0,0 +1,14 @@ +import instance from "@/hooks/useAxios.ts"; + +export const GalleryService = { + QueryKey: { + getGallery: "getGallery", + }, + + + getGallery: async (page: number) => { + const { data } = await instance.get(`/activity-gallery/?page_size=10&page=${page}`); + + return data; + }, +}; diff --git a/src/types/common.ts b/src/types/common.ts index de6cf15..44467c8 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -27,3 +27,12 @@ export type MD = { image: string; name: string; }; + +export type Gallery = { + id: number, + title: string, + content: string, + thumbnail: string, + tags: {id: number, name: string}[], + photos: string[] +}