-
Notifications
You must be signed in to change notification settings - Fork 3
[feature] 모집 상태 보기 기능을 제거하고 중앙동아리 태그를 이동한다 #759
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
Changes from all commits
ee5bc58
d5c8795
40dfe11
d8b5cbe
dee10f6
54c432e
49980cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,16 @@ | ||
| import styled from 'styled-components'; | ||
| import {media} from '@/styles/mediaQuery'; | ||
|
|
||
| export const PageContainer = styled.div` | ||
| padding: 0 40px; | ||
| max-width: 1180px; | ||
| margin: 0 auto; | ||
|
|
||
| @media (max-width: 500px) { | ||
| ${media.mobile} { | ||
| padding: 0 20px; | ||
| } | ||
|
|
||
| @media (max-width: 375px) { | ||
| ${media.mini_mobile} { | ||
| padding: 0 10px; | ||
| } | ||
| `; | ||
|
|
@@ -18,37 +19,71 @@ export const ContentWrapper = styled.div` | |
| width: 100%; | ||
| `; | ||
|
|
||
| export const SectionTabs = styled.nav` | ||
| display: flex; | ||
| gap: 18px; | ||
| margin: 60px 8px 24px; | ||
|
|
||
| ${media.mobile} { | ||
| gap: 16px; | ||
| margin: 32px 4px 16px; | ||
| } | ||
|
Comment on lines
+29
to
+30
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저번에 말씀드린 단축 속성 잘 활용하셨네요
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 덕분입니당! |
||
| `; | ||
|
|
||
| export const Tab = styled.button<{$active?: boolean}>` | ||
| display: flex; | ||
| position: relative; | ||
| font-size: 24px; | ||
| font-weight: bold; | ||
| color: ${({$active}) => $active ? '#787878' : '#DCDCDC'}; | ||
| border: none; | ||
| background: none; | ||
| cursor: pointer; | ||
|
|
||
| &::after { | ||
| content: ''; | ||
| position: absolute; | ||
| left: 0; | ||
| bottom: -4px; | ||
| width: 100%; | ||
| height: 1.5px; | ||
| background: #787878; | ||
| border-radius: 1.5px; | ||
| transform: ${({$active}) => $active ? 'scaleX(1)' : 'scaleX(0)'}; | ||
| transform-origin: center; | ||
| transition: transform 0.2s ease; | ||
| } | ||
|
|
||
| ${media.mobile} { | ||
| font-size: 14px | ||
| } | ||
| `; | ||
|
|
||
| export const CardList = styled.div` | ||
| display: grid; | ||
| width: 100%; | ||
| max-width: 100%; | ||
| gap: 35px; | ||
| margin-top: 50px; | ||
| transition: | ||
| gap 0.5s ease, | ||
| grid-template-columns 0.5s ease; | ||
|
|
||
| grid-template-columns: repeat(3, 1fr); | ||
|
|
||
| @media (max-width: 1280px) { | ||
| ${media.laptop} { | ||
| grid-template-columns: repeat(2, 1fr); | ||
| } | ||
|
|
||
| @media (max-width: 750px) { | ||
| grid-template-columns: repeat(1, 1fr); | ||
| } | ||
| @media (max-width: 500px) { | ||
|
|
||
| ${media.mobile} { | ||
| gap: 16px; | ||
| margin-top: 16px; | ||
| } | ||
| `; | ||
|
|
||
| export const FilterWrapper = styled.div` | ||
| display: flex; | ||
| justify-content: right; | ||
| margin: 20px 0; | ||
| `; | ||
|
|
||
| export const EmptyResult = styled.div` | ||
| padding: 80px 20px; | ||
| text-align: center; | ||
|
|
@@ -57,7 +92,7 @@ export const EmptyResult = styled.div` | |
| line-height: 1.6; | ||
| white-space: pre-line; | ||
|
|
||
| @media (max-width: 500px) { | ||
| ${media.mobile} { | ||
| font-size: 0.95rem; | ||
| } | ||
| `; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,6 @@ import useTrackPageView from '@/hooks/useTrackPageView'; | |
| import { useGetCardList } from '@/hooks/queries/club/useGetCardList'; | ||
| import CategoryButtonList from '@/pages/MainPage/components/CategoryButtonList/CategoryButtonList'; | ||
| import ClubCard from '@/pages/MainPage/components/ClubCard/ClubCard'; | ||
| import StatusRadioButton from '@/pages/MainPage/components/StatusRadioButton/StatusRadioButton'; | ||
| import Footer from '@/components/common/Footer/Footer'; | ||
| import Header from '@/components/common/Header/Header'; | ||
| import Banner from '@/pages/MainPage/components/Banner/Banner'; | ||
|
|
@@ -18,15 +17,18 @@ import * as Styled from './MainPage.styles'; | |
| const MainPage = () => { | ||
| useTrackPageView('MainPage'); | ||
|
|
||
| const [isFilterActive, setIsFilterActive] = useState(false); | ||
| const { selectedCategory } = useSelectedCategory(); | ||
|
|
||
| const { keyword } = useSearchKeyword(); | ||
| const { isSearching } = useSearchIsSearching(); | ||
| const recruitmentStatus = isFilterActive ? 'OPEN' : 'all'; | ||
| const recruitmentStatus = 'all'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 🧩 Analysis chainrecruitmentStatus 상수화에 따른 훅 시그니처/쿼리키 영향 점검 UI에서 모집 상태 필터를 제거했으므로 훅 인자 유지가 불필요할 수 있습니다. 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "잔존 컴포넌트/스타일 사용 여부 확인 (StatusRadioButton/FilterWrapper)"
rg -n -C2 --type=ts --type=tsx "\bStatusRadioButton\b|FilterWrapper\b" frontend || true
echo "recruitmentStatus 사용처 확인"
rg -n -C2 --type=ts --type=tsx "\brecruitmentStatus\b" frontend || true
echo "useGetCardList 정의/파라미터 확인"
rg -n -C3 --type=ts --type=tsx "(export\s+(const|function)\s+useGetCardList\b|function\s+useGetCardList\s*\()" frontend || trueLength of output: 189 rg의 --type=tsx 옵션 때문에 검색이 실패했습니다. 아래 스크립트로 타입 필터 없이 재검색해 주세요: 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "잔존 컴포넌트/스타일 사용 여부 확인 (StatusRadioButton / FilterWrapper)"
rg -n -C2 "\bStatusRadioButton\b|\bFilterWrapper\b" frontend || true
echo "recruitmentStatus 사용처 확인"
rg -n -C2 "\brecruitmentStatus\b" frontend || true
echo "useGetCardList 정의/파라미터(함수/const export) 및 호출 확인"
rg -n -C3 "export\s+(const|function)\s+useGetCardList\b|function\s+useGetCardList\s*\(|\buseGetCardList\s*\(" frontend || trueLength of output: 8889 recruitmentStatus 제거 및 useGetCardList 시그니처·쿼리키 정리 필요 검증: useGetCardList 정의는 frontend/src/hooks/queries/club/useGetCardList.ts이고 호출지는 frontend/src/pages/MainPage/MainPage.tsx(현재 recruitmentStatus = 'all' 상수 전달) 한 곳뿐입니다. 조치(요약):
|
||
| const division = 'all'; | ||
| const searchCategory = isSearching ? 'all' : selectedCategory; | ||
|
|
||
| const tabs = ['중앙동아리'] as const; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as const를 사용하신 이유가뭔가요?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as const를 사용하지 않아도 큰 문제는 없지만, "중앙동아리"처럼 탭은 값이 정해져 있는 집합이기 때문에 읽기 전용으로 두는게 좋을 것 같다고 생각했습니다ㅏ const tabs = ['중앙동아리', '가동아리', '과동아리'] as const;
const [active, setActive] = useState<typeof tabs[number]>('중앙동아리');위의 코드처럼 tabs의 값들로부터 타입을 바로 추론해 active를 관리하면, 항상 tabs 안의 값만 선택할 수 있게 됩니당 간결하게 작성할 수도 있고, 타입 안정성을 확보할 수 있어서 as const를 사용했어요~
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tab에 들어갈 동아리 타입을 조금 멀리 보면 API 응답에서 // 예시
// types/club.ts
export type DivisionKey = '중동' | '가동' | '과동';
export interface Club {
id: string;
name: string;
logo: string;
tags: string[];
recruitmentStatus: string;
division: DivisionKey; // ← 문자열 대신 타입으로 관리
category: string;
introduction: string;
}
export const DivisionLabel: Record<DivisionKey, string> = {
중동: '중앙동아리',
가동: '가동아리',
과동: '과동아리',
};
// 사용할 때
const tabs: DivisionKey[] = ['중동', '과동'];다만 현재 API가 "중동"처럼 태그 형태로 내려주다 보니 매핑 로직이 꼭 필요하겠네요. 수현님이 사용하신 as const 방식도 타입 안정성을 챙기려는 의도가 잘 드러나서 좋았습니다~ 🙂
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 좋은 조언 감사합니다ㅏ 추후 확장성을 고려해서 준서님께서 제시해주신 부분을 참고할 수 있도록 //TODO 주석으로 남겨뒀습니다ㅏ 감사합니당 |
||
| const [active, setActive] = useState<typeof tabs[number]>('중앙동아리'); | ||
| // TODO: 추후 확정되면 DivisionKey(중동/가동/과동) 같은 타입을 | ||
| // types/club.ts에 정의해서 tabs 관리하도록 리팩터링하기 | ||
|
|
||
| const { | ||
| data: clubs, | ||
| error, | ||
|
|
@@ -53,9 +55,14 @@ const MainPage = () => { | |
| /> | ||
| <Styled.PageContainer> | ||
| <CategoryButtonList /> | ||
| <Styled.FilterWrapper> | ||
| <StatusRadioButton onChange={setIsFilterActive} /> | ||
| </Styled.FilterWrapper> | ||
| <Styled.SectionTabs> | ||
| {tabs | ||
| .map((tab) =>( | ||
| <Styled.Tab key={tab} $active={active===tab} onClick={() => setActive(tab)}> | ||
| {tab} | ||
| </Styled.Tab> | ||
| ))} | ||
| </Styled.SectionTabs> | ||
|
Comment on lines
+58
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. list로 탭관리하는 부분 좋네요 |
||
| <Styled.ContentWrapper> | ||
| {isLoading ? ( | ||
| <Spinner /> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,14 @@ | ||
| export const BREAKPOINT = { | ||
| mobile: 500, | ||
| tablet: 900, | ||
| mini_mobile: 375, // ≤ 375 | ||
| mobile: 500, // ≤ 500 | ||
| tablet: 700, // ≤ 700 | ||
| laptop: 1280, // ≤ 1280 | ||
| }; | ||
|
|
||
| export const media = { | ||
| mini_mobile: `@media (max-width: ${BREAKPOINT.mini_mobile}px)`, | ||
| mobile: `@media (max-width: ${BREAKPOINT.mobile}px)`, | ||
| tablet: `@media (max-width: ${BREAKPOINT.tablet}px)`, | ||
| }; | ||
| laptop: `@media (max-width: ${BREAKPOINT.laptop}px)`, | ||
| // 1281px 이상은 기본 스타일 (desktop) | ||
| }; |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
navsemantic 태그 사용해주신거 좋네요~접근성까지 잘 챙기신 것 같아요 👏