Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
80 changes: 80 additions & 0 deletions src/app/shared/components/common/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use client'

import Image from 'next/image'

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)

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">사용자</span>
</div>
Comment on lines +50 to +62
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

imageUrl 프롭이 무시되고 있습니다

imageUrl이 truthy여도 실제로는 하드코딩된 /images/profile.gif를 렌더링하고 nickname 대신 "사용자" 텍스트를 표기하고 있습니다. 이는 명백한 기능 오류입니다.

- <Image
-   src="/images/profile.gif"
-   fill
-   alt="프로필 이미지"
-   className="size-full object-cover"
- />
+ <Image
+   src={imageUrl}
+   fill
+   alt={`${nickname} 프로필 이미지`}
+   className="size-full object-cover"
+ />
...
- <span className="text-sm font-semibold">사용자</span>
+ <span className="text-sm font-semibold">{nickname}</span>

또한 컨테이너에 style={{ width: size, height: size }} 를 동일하게 적용하여 size 프롭을 일관되게 반영해 주세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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">사용자</span>
</div>
return imageUrl ? (
// 프로필 이미지가 있을 때
<div className="flex items-center gap-4">
<div className="relative size-48 overflow-hidden rounded-full">
<Image
src={imageUrl}
fill
alt={`${nickname} 프로필 이미지`}
className="size-full object-cover"
/>
</div>
<span className="text-sm font-semibold">{nickname}</span>
</div>
🤖 Prompt for AI Agents
In src/app/shared/components/common/Profile.tsx around lines 50 to 62, the
imageUrl prop is ignored because the Image component always uses the hardcoded
"/images/profile.gif" source and the nickname is replaced with the fixed text
"사용자". To fix this, update the Image src to use the imageUrl prop and replace
the fixed nickname text with the nickname prop. Also, apply the style attribute
with width and height set to the size prop on the container div to ensure
consistent sizing.

) : (
// 프로필 이미지가 없을 때
<>
<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>
</>
)
}
40 changes: 15 additions & 25 deletions src/app/shared/components/common/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
'use client'

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 상태

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 +24,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 +41,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 +53,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,20 +62,12 @@ 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">
마이페이지
</button>
<button onClick={logout} className="text-xs">
<button onClick={goToMypage} className="text-xs">
로그아웃
</button>
</>
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))
}
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