Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ body {
.Text-gray {
@apply text-[#787486] dark:text-[#BCBCBC];
}
.Text-white {
@apply text-[#FFFFFF] dark:text-[#333236];
}
.Border-btn {
@apply border border-[#D9D9D9] dark:border-[#747474];
}
Expand Down
81 changes: 81 additions & 0 deletions src/app/shared/components/common/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use client'

import Image from 'next/image'
import { useUserStore } from '@store/useUserStore'

type ProfileProps = {
nickname: string
imageUrl?: string
size?: number
}

const customColors = [
'#efaa8d',
'#FFC85A',
'#b9ef8d',
'#8eef8d',
'#8defd3',
'#8dcaef',
'#8d9def',
'#a58def',
'#e292e0',
]

// 첫 글자로 사용자 프로필 생성하는 함수
function getInitial(nickname: string): string {
const firstChar = nickname.trim().charAt(0)

if (/[a-zA-Z]/.test(firstChar)) {
return firstChar.toUpperCase() // 영어: 대문자
}

if (/[가-힣]/.test(firstChar)) {
return firstChar // 한글은 그대로 반환
}

return '?' // 기타문자: 물음표
}

// 닉네임으로부터 배경색 생성 함수
function getColor(nickname: string): string {
const hash = nickname
.split('')
.reduce((acc, char) => acc + char.charCodeAt(0), 0)
return customColors[hash % customColors.length]
}

export function Profile({ nickname, imageUrl, size = 36 }: ProfileProps) {
const initial = getInitial(nickname)
const bgColor = getColor(nickname)

const { user } = useUserStore()

return imageUrl ? (
<div className="flex items-center gap-4">
<div className="relative size-48 overflow-hidden rounded-full">
<Image
src="/images/profile.gif"
fill
alt="프로필 이미지"
className="size-full object-cover"
/>
</div>
<span className="text-sm font-semibold">사{user?.name}</span>
</div>
) : (
<>
<div
className="ml-8 flex items-center justify-center rounded-full font-semibold text-white"
style={{
width: size,
height: size,
fontSize: size * 0.4, // 글자 크기 조정
backgroundColor: bgColor,
}}
>
{initial}
</div>
<div className="text-base font-medium">{nickname}</div>
</>
)
}
38 changes: 15 additions & 23 deletions src/app/shared/components/common/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

import { useUserStore } from '@store/useUserStore' // Zustand 예시
import { usePathname, useRouter } from 'next/navigation'
import { cn } from '@lib/cn' // 클래스 이름 병합 유틸리티
import Link from 'next/link'
import Image from 'next/image'
import { Profile } from '@components/common/Profile'

export default function Header() {
const pathname = usePathname()
const router = useRouter()
const goToMypage = () => {
router.push('/mypage')
}
const { user, logout } = useUserStore() // Zustand 상태
const { logout } = useUserStore() // Zustand 상태

return (
<header className="flex items-center justify-between border-b border-gray-200 bg-white px-36 py-16 dark:border-gray-700 dark:bg-black">
<header className="BG-White Border-section Text-black flex items-center justify-between border-b px-36 py-16">
{/* 좌측 대시보드명 */}
<div className="flex items-center gap-8">
<div className="font-bold">대시보드 명</div>
Expand All @@ -24,12 +26,15 @@ export default function Header() {
</div>

{/* 우측 사용자 정보/다크모드 */}
<div className="flex items-center gap-16">
<div className="flex items-center gap-8">
<>
<nav className="hidden gap-8 text-sm text-gray-600 dark:text-gray-300 md:flex">
<Link
href="/dashboard"
className={`flex items-center gap-6 rounded-md border-2 border-solid px-8 py-4 ${pathname === '/dashboard' ? 'font-semibold' : ''}`}
className={cn(
'Border-btn flex items-center gap-6 rounded-md border-solid px-12 py-6',
pathname === '/dashboard' && 'font-semibold',
)}
>
<div className="relative flex size-12">
<Image src="/images/management.png" fill alt="관리 버튼" />
Expand All @@ -38,7 +43,10 @@ export default function Header() {
</Link>
<Link
href="/modal"
className={`flex items-center gap-6 rounded-6 border-2 border-solid px-8 py-4 ${pathname === '/modal' ? 'font-semibold' : ''}`}
className={cn(
'Border-btn mr-16 flex items-center gap-6 rounded-6 border-solid px-12 py-6',
pathname === '/modal' && 'font-semibold',
)}
>
<div className="relative flex size-12">
<Image src="/images/invitation.png" fill alt="초대 버튼" />
Expand All @@ -47,15 +55,7 @@ export default function Header() {
</Link>
</nav>
{/* 공동작업자 프로필 이미지 */}
<div className="relative size-48 overflow-hidden rounded-full">
<Image
src="/images/collaborator.png"
fill
alt="초대된 사용자"
style={{ objectFit: 'cover' }}
/>
</div>
<div className="relative size-48 overflow-hidden rounded-full">
<div className="relative mx-16 size-48 overflow-hidden rounded-full">
<Image
src="/images/collaborator.png"
fill
Expand All @@ -64,15 +64,7 @@ export default function Header() {
/>
</div>
|{/* 내 프로필 이미지 */}
<div className="relative size-48 overflow-hidden rounded-full">
<Image
src="/images/profile.gif"
fill
alt="프로필이미지"
style={{ objectFit: 'cover' }}
/>
</div>
<span className="text-sm">배유철 {user?.name}</span>
<Profile nickname="전유진" />
{/* 드롭다운 메뉴 */}
<button onClick={goToMypage} className="text-xs">
마이페이지
Expand Down
6 changes: 6 additions & 0 deletions src/app/shared/lib/cn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
2 changes: 1 addition & 1 deletion src/app/shared/store/useUserStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { create } from 'zustand'
import { persist } from 'zustand/middleware'

import { User } from '../types/User.interface'
import { User } from '../types/user.type'

interface UserState {
user: User | null
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"@/*": ["./src/*"],
"@components/*": ["./src/app/shared/components/*"],
"@store/*": ["./src/app/shared/store/*"],
"@hooks/*": ["./src/app/shared/hooks/*"]
"@hooks/*": ["./src/app/shared/hooks/*"],
"@lib/*": ["./src/app/shared/lib/*"]
}
},
"include": [
Expand Down