-
Notifications
You must be signed in to change notification settings - Fork 2
✨ feat: 사이드바 컴포넌트 구현 #42
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 1 commit
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 |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| 'use client' | ||
|
|
||
| import Image from 'next/image' | ||
|
|
||
| import { CreateDashboardButtonProps } from '@/app/shared/types/dashboard' | ||
|
|
||
| export default function CreateDashboardButton({ | ||
| onClick, | ||
| }: CreateDashboardButtonProps): JSX.Element { | ||
| return ( | ||
| <button | ||
| onClick={onClick} | ||
| className="flex size-20 items-center justify-center rounded-6 transition-colors hover:bg-gray-50" | ||
| aria-label="새 대시보드 생성" | ||
| > | ||
| <div className="relative size-16"> | ||
| <Image | ||
| src="/images/invitation.png" | ||
| alt="대시보드 생성" | ||
| fill | ||
| className="object-contain" | ||
| /> | ||
| </div> | ||
| </button> | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| 'use client' | ||
|
|
||
| import Image from 'next/image' | ||
|
|
||
| import { DashboardItemProps } from '@/app/shared/types/dashboard' | ||
|
|
||
| export default function DashboardItem({ | ||
| dashboard, | ||
| isActive = false, | ||
| onClick, | ||
| }: DashboardItemProps): JSX.Element { | ||
| const handleClick = () => { | ||
| onClick(dashboard.id) | ||
| } | ||
|
|
||
| return ( | ||
| <button | ||
| onClick={handleClick} | ||
| className={`Text-black flex w-full items-center gap-12 rounded-6 px-12 py-8 text-left text-18 transition-colors hover:bg-gray-50 ${ | ||
| isActive ? 'BG-currentDashboard font-medium' : '' | ||
| }`} | ||
| > | ||
| {/* 컬러 도트 */} | ||
| <div | ||
| className="size-8 flex-shrink-0 rounded-full" | ||
| style={{ backgroundColor: dashboard.color }} | ||
| /> | ||
|
|
||
| {/* 대시보드 제목 */} | ||
| <span className="flex-1 truncate">{dashboard.title}</span> | ||
|
|
||
| {/* 내가 만든 대시보드에 왕관 아이콘 */} | ||
| {dashboard.createdByMe && ( | ||
| <div className="relative h-12 w-14 flex-shrink-0"> | ||
| <Image | ||
| src="/images/crown.png" | ||
| alt="내가 만든 대시보드" | ||
| fill | ||
| className="object-contain" | ||
| /> | ||
| </div> | ||
| )} | ||
| </button> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| 'use client' | ||
|
|
||
| import Image from 'next/image' | ||
| import Link from 'next/link' | ||
| import { usePathname, useRouter } from 'next/navigation' | ||
|
|
||
| import CreateDashboardButton from './CreateDashboardButton' | ||
| import DashboardItem from './DashboardItem' | ||
|
|
||
| export default function Sidebar(): JSX.Element { | ||
|
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.
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.
|
||
| const pathname = usePathname() | ||
| const router = useRouter() | ||
|
|
||
| // TODO: 목데이터 - API 연동시 삭제예정 | ||
| const mockDashboards = [ | ||
| { | ||
| id: 1, | ||
| title: '비브러리', | ||
| color: '#10B981', | ||
| createdByMe: true, | ||
| createdAt: '', | ||
| updatedAt: '', | ||
| userId: 1, | ||
| }, | ||
| { | ||
| id: 2, | ||
| title: '코드잇', | ||
| color: '#8B5CF6', | ||
| createdByMe: true, | ||
| createdAt: '', | ||
| updatedAt: '', | ||
| userId: 1, | ||
| }, | ||
| { | ||
| id: 3, | ||
| title: '3분기 계획', | ||
| color: '#F59E0B', | ||
| createdByMe: false, | ||
| createdAt: '', | ||
| updatedAt: '', | ||
| userId: 2, | ||
| }, | ||
| { | ||
| id: 4, | ||
| title: '회의록', | ||
| color: '#3B82F6', | ||
| createdByMe: false, | ||
| createdAt: '', | ||
| updatedAt: '', | ||
| userId: 3, | ||
| }, | ||
| { | ||
| id: 5, | ||
| title: '중요 문서함', | ||
| color: '#EC4899', | ||
| createdByMe: false, | ||
| createdAt: '', | ||
| updatedAt: '', | ||
| userId: 4, | ||
| }, | ||
| ] | ||
|
|
||
| const handleDashboardClick = (dashboardId: number) => { | ||
| router.push(`/dashboard/${dashboardId}`) | ||
| } | ||
|
|
||
| const handleCreateDashboard = () => { | ||
| // TODO: 대시보드 생성 모달 열기 | ||
| console.log('대시보드 생성 모달 열기임') | ||
| } | ||
| return ( | ||
| <aside className="BG-white Border-section fixed left-0 top-0 h-screen w-300 overflow-y-auto"> | ||
| {/* 로고 섹션 */} | ||
| <div className="flex h-70 items-center px-20"> | ||
| <Link href="/" className="flex items-center gap-8"> | ||
| <div className="relative h-35 w-150"> | ||
| <Image | ||
| src="/images/logo-light2.svg" | ||
| alt="Coplan logo" | ||
| fill | ||
| className="object-contain" | ||
| priority | ||
| /> | ||
| </div> | ||
| </Link> | ||
| </div> | ||
|
|
||
| {/* 대시보드 섹션 */} | ||
| <div className="px-20 py-24"> | ||
| {/* 섹션 헤더 */} | ||
| <div className="mb-24 flex items-center justify-between"> | ||
| <h2 className="Text-gray text-12 font-semibold">Dash Boards</h2> | ||
| <CreateDashboardButton onClick={handleCreateDashboard} /> | ||
| </div> | ||
|
|
||
| {/* 대시보드 목록 */} | ||
| <div className="space-y-8"> | ||
| {mockDashboards.map((dashboard) => ( | ||
| <DashboardItem | ||
| key={dashboard.id} | ||
| dashboard={dashboard} | ||
| isActive={pathname === `/dashboard/${dashboard.id}`} | ||
| onClick={handleDashboardClick} | ||
| /> | ||
| ))} | ||
| </div> | ||
| </div> | ||
|
Comment on lines
+89
to
+107
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. 이 부분은 추후에 시멘틱까지 고려한다면
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. 감사합니다 :) 추후에 여유가 생기면 시멘틱까지 고려해서 수정해봐야겠네요.
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. 👍👍 |
||
| </aside> | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // 사이드바용 대시보드 타입 | ||
| export interface Dashboard { | ||
| id: number | ||
| title: string | ||
| color: string | ||
| createdAt: string | ||
| updatedAt: string | ||
| createdByMe: boolean | ||
| userId: number | ||
| } | ||
|
|
||
| // 대시보드 목록 조회 응답 | ||
| export interface DashboardListResponse { | ||
| cursorId: number | ||
| totalCount: number | ||
| dashboards: Dashboard[] | ||
| } | ||
|
|
||
| // 사이드바 컴포넌트 Props | ||
| export interface DashboardItemProps { | ||
| dashboard: Dashboard | ||
| isActive?: boolean | ||
| onClick: (dashboardId: number) => void | ||
| } | ||
|
|
||
| export interface CreateDashboardButtonProps { | ||
| onClick: () => void | ||
| } | ||
|
|
||
| // 대시보드 생성 요청 타입 | ||
| export interface CreateDashboardRequest { | ||
| title: string | ||
| color: string | ||
| } |
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.
background 색상의 경우 global 스타일로 빼서 사용하면 좋지 않을까 합니다!!
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.
감사합니다 :) 중복으로 사용할 일이 생기면 global 스타일로 빼서 올려두겠습니다 👍