-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 어드민 대시보드 페이지 추가 #197
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
Merged
Merged
Changes from all commits
Commits
Show all changes
58 commits
Select commit
Hold shift + click to select a range
6b75c81
feat: 현재 선택된 대회명 가져오는 공통 훅 생성
koty08 036ac9f
feat: 대회명 수정 컴포넌트 생성
koty08 de1a459
feat: 대회 삭제 컴포넌트 생성
koty08 d6d6f19
feat: 대회 관리 페이지 생성 및 라우팅 설정
koty08 bdb674b
fix: AdminContestLayout 컨텐츠 영역 flex-1 적용
koty08 0375366
feat: 현재 진행중인 대회 설정 컴포넌트 추가
koty08 9a6fcba
feat: 모달 위한 radix-ui dialog 라이브러리 설치 및 커스터마이징
koty08 bf6d49b
feat: admin 페이지에서 사용할 합성 컴포넌트 모음 추가
koty08 6e21141
feat: 대회 카테고리 섹션 및 추가/수정/삭제 모달 컴포넌트 작업
koty08 52cc2cd
feat: 대회 목록 섹션 컴포넌트 추가
koty08 c46c2f7
feat: 전체 공지사항 섹션 추가 및 추가/수정 모달 컴포넌트 작업
koty08 b4259c0
feat: 서비스 관련 정보 섹션 컴포넌트 추가
koty08 a17fd3d
feat: 어드민 메인(대시보드)페이지 추가 및 라우팅 설정
koty08 1684a59
feat: 어드민 공통 삭제 확인 모달 추가
koty08 ac738f1
design: 모달 X 버튼 위치, 패딩 수정
koty08 95bf063
fix: 카테고리 생성 모달도 Controlled 하게 설정, 삭제 확인 모달 공통으로 수정
koty08 a03c9b1
fix: 모달 Title 컴포넌트 추가 및 적용
koty08 41eacf4
feat: 대회 카테고리 DTO 및 Fetcher 정의
koty08 8785117
feat: 카테고리 CRUD API 연결
koty08 a321df4
feat: 대회 전체 조회에 DTO 현재 진행 상태, 카테고리 추가
koty08 b52194e
feat: 전체 대회 조회 queryOption 추가, 현재 대회 상태 변경 Fetcher 추가
koty08 e32ce15
feat: 전체 대회 조회 및 현재 대회 상태 변경 API 컴포넌트에 연결, ContestSlots 컴포넌트 별도 분리
koty08 e1fee23
fix: 기존 공지사항 DTO 내 날짜 형식 Date -> string으로 수정
koty08 dae7482
refactor: 공지사항 및 공지사항 상세 API QueryOption으로 별도 분리
koty08 5ff73ed
feat: 대회 생성 단계 및 생성된 대회 ID 관리 위한 ContextProvider 생성
koty08 827066e
feat: 카테고리 선택 드롭다운 컴포넌트 생성 (대회 관리에서 추후 활용)
koty08 8787256
feat: 대회 생성 단계 UI 컴포넌츠 생성
koty08 4166e72
feat: 대회 생성 1단계 컴포넌트 생성
koty08 b2f9299
chore: 템플릿 파일 public 폴더 내 추가
koty08 69cef09
feat: 대회 생성 2단계 - 대회 참여자 설정 컴포넌트 생성
koty08 8a053eb
feat: 대회 생성 3단계 - 필수 항목 설정 컴포넌트 틀만 우선 생성
koty08 8dd84b4
feat: 대회 생성 페이지 및 라우팅 설정
koty08 486e3a6
Merge branch 'feat/contest-create' into feat/contest-manage
koty08 fbcb076
feat: 대회 수정 부분 대회 카테고리 컴포넌트 사용, 카테고리도 함께 수정할 수 있게 변경
koty08 58a093e
style: 대회 삭제 버튼 스타일 수정
koty08 09398c8
refactor: 미사용 레거시 코드 삭제
koty08 8fe9681
refactor: queryOption으로 변경
koty08 0e8136a
fix: 전체 공지사항 모달 닫기 버그 수정, mutation 관련 로직 수정
koty08 99b3ed4
fix: 카테고리 삭제 모달 onDelete 잘못 설정된 부분 수정
koty08 9d4eb4d
feat: 공지사항 삭제 확인 모달 추가
koty08 f88cc3a
fix: 카테고리 CUD 이후 리스트 API 리패칭하도록 수정
koty08 e791185
design: 공지사항 목록 border 색상 수정
koty08 db2931e
fix: 전체 공지사항 삭제 후 리패칭 하도록 수정, 삭제 모달 안열리는 버그 수정
koty08 521b4d9
fix: 진행중 대회 해제 시 refetch로 인한 select 값 초기화 버그 수정
koty08 a6bad4b
design: 대회 목록 아이템에 카테고리명 추가
koty08 97c6e70
fix: 대회 목록 부분 누락된 key 추가
koty08 722d1a3
Merge branch 'feat/contest-manage' into feat/admin-dashboard
koty08 4ba1a74
feat: 데이터 없는 경우 공통 UI 추가, 어드민 메인 페이지에 적용
koty08 ece253e
Merge branch 'develop' into feat/admin-dashboard
koty08 0567c5f
refactor: 기존 twMerge 부분 cn 공통 유틸함수로 변경
koty08 35c5ecf
fix: AdminNoData 컴포넌트 className 부분 style로 잘못 작성된 부분 수정
koty08 dda330b
fix: 대회 리스트 아이템의 링크 영역 AdminCardRow 전체로 변경
koty08 93b945b
feat: 카테고리명 API 호출 전 trim 처리
koty08 69b2a8d
style: 진행 중 대회 설정 삭제 버튼 스타일 수정, 서비스 관련 정보 스타일 수정
koty08 ebf90fe
feat: 전체 공지사항 목록 ID 출력 부분 제거
koty08 0ed4c7b
fix: 카테고리, 전체 공지사항 추가 이후 입력값 초기화 처리
koty08 958d1fc
style: 전체 공지사항 영역에 스크롤 추가
koty08 372a822
Merge branch 'develop' into feat/admin-dashboard
koty08 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { CategoryDto } from 'types/DTO'; | ||
| import apiClient from './apiClient'; | ||
|
|
||
| export const getAllCategory = async () => { | ||
| const res = await apiClient.get<CategoryDto[]>('/categories'); | ||
| return res.data; | ||
| }; | ||
|
|
||
| export const postCategory = async (categoryName: string) => { | ||
| const res = await apiClient.post('/categories', { categoryName }); | ||
| return res.data; | ||
| }; | ||
|
|
||
| export const patchCategory = async (categoryId: number, categoryName: string) => { | ||
| const res = await apiClient.patch(`/categories/${categoryId}`, { categoryName }); | ||
| return res.data; | ||
| }; | ||
|
|
||
| export const deleteCategory = async (categoryId: number) => { | ||
| const res = await apiClient.delete(`/categories/${categoryId}`); | ||
| return res.data; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| import { VscKebabVertical } from 'react-icons/vsc'; | ||
| import { LuPencil } from 'react-icons/lu'; | ||
| import { FaRegTrashAlt } from 'react-icons/fa'; | ||
| import { Popover, PopoverContent, PopoverTrigger } from './popover'; | ||
| import { DialogClose, DialogContent, DialogTitle } from './dialog'; | ||
| import Button from '@components/Button'; | ||
| import { cn } from '@components/lib/utils'; | ||
|
|
||
| export const AdminCard = ({ children }: React.ComponentProps<'div'>) => { | ||
| return <div className="border-lightGray flex flex-col gap-0.5 rounded-xl border-2">{children}</div>; | ||
| }; | ||
|
|
||
| export const AdminCardTop = ({ children }: React.ComponentProps<'div'>) => { | ||
| return <div className="border-lightGray flex items-center justify-between border-b px-5 py-4">{children}</div>; | ||
| }; | ||
|
|
||
| export const AdminCardCreateButton = ({ children, ...props }: React.ComponentProps<'button'>) => { | ||
| return ( | ||
| <button className="text-midGray hover:text-mainBlue rounded-xl px-[15px] py-2.5 font-bold" {...props}> | ||
| {children} | ||
| </button> | ||
| ); | ||
| }; | ||
|
|
||
| export const AdminCardRow = ({ children, className }: React.ComponentProps<'div'>) => { | ||
| return <div className={cn('flex items-center justify-between px-5 py-3', className)}>{children}</div>; | ||
| }; | ||
|
|
||
| export const AdminPopoverMenu = ({ children, ...props }: React.ComponentProps<'div'>) => { | ||
| return ( | ||
| <Popover> | ||
| <PopoverTrigger asChild> | ||
| <button className="group rounded-4xl px-2 py-2 hover:bg-blue-100"> | ||
| <VscKebabVertical size={16} className="group-hover:fill-mainBlue fill-midGray" /> | ||
| </button> | ||
| </PopoverTrigger> | ||
| <PopoverContent className="w-fit p-1.5"> | ||
| <div className="flex w-[70px] flex-col gap-1" {...props}> | ||
| {children} | ||
| </div> | ||
| </PopoverContent> | ||
| </Popover> | ||
| ); | ||
| }; | ||
|
|
||
| export const AdminPopoverEditButton = ({ onEdit }: { onEdit: () => void }) => { | ||
| return ( | ||
| <button className="hover:bg-whiteGray flex items-center gap-2.5 rounded-sm p-1 text-sm" onClick={onEdit}> | ||
| <LuPencil size={16} className="mt-1" /> | ||
| 수정 | ||
| </button> | ||
| ); | ||
| }; | ||
|
|
||
| export const AdminPopoverDeleteButton = ({ onDelete }: { onDelete: () => void }) => { | ||
| return ( | ||
| <button | ||
| className="hover:bg-whiteGray flex items-center gap-2.5 rounded-sm p-1 text-sm text-red-500" | ||
| onClick={onDelete} | ||
| > | ||
| <FaRegTrashAlt size={16} className="mt-1 fill-red-500" /> | ||
| 삭제 | ||
| </button> | ||
| ); | ||
| }; | ||
|
|
||
| export const AdminDeleteConfirmModal = ({ title, onDelete }: { title: string; onDelete: () => void }) => { | ||
| return ( | ||
| <DialogContent className="gap-6"> | ||
| <DialogTitle className="text-center text-lg font-semibold text-gray-800">{title}</DialogTitle> | ||
| <div className="flex justify-center gap-4"> | ||
| <DialogClose asChild> | ||
| <Button className="border-lightGray text-midGray rounded-full border px-4 py-2 hover:bg-gray-100"> | ||
| {'닫기'} | ||
| </Button> | ||
| </DialogClose> | ||
| <Button className="rounded-full bg-red-700 px-4 py-2" onClick={onDelete}> | ||
| {'삭제'} | ||
| </Button> | ||
| </div> | ||
| </DialogContent> | ||
| ); | ||
| }; | ||
|
|
||
| export const AdminNoData = ({ className }: React.ComponentProps<'div'>) => { | ||
| return ( | ||
| <div className={cn('text-midGray my-10 flex items-center justify-center font-bold', className)}> | ||
| 데이터가 없습니다. | ||
| </div> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| import * as React from 'react'; | ||
| import * as DialogPrimitive from '@radix-ui/react-dialog'; | ||
| import { RxCross2 } from 'react-icons/rx'; | ||
|
|
||
| import { cn } from '@components/lib/utils'; | ||
|
|
||
| function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) { | ||
| return <DialogPrimitive.Root data-slot="dialog" {...props} />; | ||
| } | ||
|
|
||
| function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.DialogTrigger>) { | ||
| return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />; | ||
| } | ||
|
|
||
| function DialogContent({ className, children, ...props }: React.ComponentProps<typeof DialogPrimitive.Content>) { | ||
| return ( | ||
| <DialogPrimitive.Portal> | ||
| <DialogPrimitive.Overlay | ||
| data-slot="dialog-overlay" | ||
| className="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/30" | ||
| /> | ||
| <DialogPrimitive.Content | ||
| data-slot="dialog-content" | ||
| aria-describedby={undefined} | ||
| className={cn( | ||
| 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-1/2 left-1/2 z-50 grid w-fit -translate-x-1/2 -translate-y-1/2 flex-col items-center gap-4 border p-7 pt-9 pr-9 shadow-lg duration-200 sm:rounded-lg', | ||
| className, | ||
| )} | ||
| {...props} | ||
| > | ||
| {children} | ||
| <DialogPrimitive.Close | ||
| asChild | ||
| className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-2 right-2 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none" | ||
| > | ||
| <button> | ||
| <RxCross2 size={20} /> | ||
| <span className="sr-only">Close</span> | ||
| </button> | ||
| </DialogPrimitive.Close> | ||
| </DialogPrimitive.Content> | ||
| </DialogPrimitive.Portal> | ||
| ); | ||
| } | ||
|
|
||
| function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) { | ||
| return ( | ||
| <DialogPrimitive.Title data-slot="dialog-title" asChild> | ||
| <h3 className={cn('"text-center text-gray-800" text-lg font-semibold', className)} {...props} /> | ||
| </DialogPrimitive.Title> | ||
| ); | ||
| } | ||
|
|
||
| function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) { | ||
| return <DialogPrimitive.Close data-slot="dialog-close" {...props} />; | ||
| } | ||
|
|
||
| export { Dialog, DialogTrigger, DialogContent, DialogTitle, DialogClose }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { useParams } from 'react-router-dom'; | ||
| import useContests from './useContests'; | ||
|
|
||
| const useContestName = () => { | ||
| const { contestId: contestIdParam } = useParams(); | ||
| const { data: contests } = useContests(); | ||
| const contestName = contests?.find((contest) => contest.contestId === Number(contestIdParam))?.contestName; | ||
|
|
||
| return contestName; | ||
| }; | ||
|
|
||
| export default useContestName; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
src/components/ui 디렉토리는 shadcn 컴포넌트들이 위치하는 곳으로 알고 있습니다. 현재 디렉토리에 해당 파일이 위치할 경우 헷갈릴 수 있을 것 같아요 다른 적절한 위치로 파일을 이동하는 것은 어떨까요?
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.
현재 @redzzzi 님께서도 해당 admin 파일 수정 사항이 feature 브랜치에 존재하여, 추후 머지된 이후에 위치 수정하도록 하겠습니다!