Skip to content
Open
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
33 changes: 22 additions & 11 deletions src/pages/my/components/MenuListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ChevronRightIcon from '@/assets/icons/my/chevron-right.svg?react'
interface MenuListItemProps {
icon?: ComponentType<SVGProps<SVGSVGElement>>
label: string
description?: string
onClick?: () => void
isLast?: boolean
iconClassName?: string
Expand All @@ -12,6 +13,7 @@ interface MenuListItemProps {
export function MenuListItem({
icon: Icon,
label,
description,
onClick,
isLast = false,
iconClassName,
Expand All @@ -20,23 +22,32 @@ export function MenuListItem({
<button
type="button"
onClick={onClick}
className={`flex h-14 w-full items-center gap-2.5 pl-[18px] pr-4 ${
isLast ? '' : 'border-b border-line-2'
className={`group flex min-h-14 w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-bg-light/70 active:bg-bg-dark ${
isLast ? '' : 'border-b border-line-1'
}`}
>
{Icon && (
<Icon
className={`h-5 w-5 shrink-0 [&_*]:!stroke-current ${
iconClassName ?? 'text-text-100'
}`}
aria-hidden="true"
/>
<span className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-main-100">
<Icon
className={`h-5 w-5 shrink-0 [&_*]:!stroke-current ${
iconClassName ?? 'text-sub'
}`}
aria-hidden="true"
/>
</span>
)}
<span className="flex-1 text-left text-text-100 typography-body01-regular">
{label}
<span className="flex flex-1 flex-col gap-0.5">
<span className="text-text-100 typography-body01-semibold">
{label}
</span>
{description && (
<span className="text-text-70 typography-body03-regular">
{description}
</span>
)}
</span>
<ChevronRightIcon
className="h-5 w-5 shrink-0 text-text-100"
className="h-5 w-5 shrink-0 text-text-50 transition-transform group-hover:translate-x-0.5"
aria-hidden="true"
/>
</button>
Expand Down
30 changes: 18 additions & 12 deletions src/pages/my/components/ProfileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,25 @@ export function ProfileCard({
const roleLabel = isManager ? '사장님' : '알바생'

return (
<div className="relative flex h-[120px] w-full flex-col justify-center rounded-2xl bg-white pl-[18px] pr-4">
<section className="relative overflow-hidden rounded-3xl bg-white p-5 shadow-[0_8px_24px_rgba(35,35,35,0.06)]">
<div className="flex items-center gap-3.5">
<Avatar src={avatarUrl} alt={`${nickname} 프로필 이미지`} size={60} />
<div className="flex flex-col items-start justify-center gap-0.5">
<Avatar
src={avatarUrl}
alt={`${nickname} 프로필 이미지`}
size={64}
className="ring-4 ring-white"
/>
<div className="relative flex min-w-0 flex-1 flex-col items-start justify-center gap-1">
<p className="text-text-100 typography-headline01">{nickname}</p>
<div className="flex items-center gap-2">
<div className="flex items-center gap-0.5 text-main-900">
<CrownIcon className="size-5" aria-hidden="true" />
<span className="typography-body02-regular">{roleLabel}</span>
<div className="flex items-center gap-1 rounded-full bg-white/90 px-2 py-1 text-sub shadow-sm">
<CrownIcon className="size-4" aria-hidden="true" />
<span className="typography-body03-semibold">{roleLabel}</span>
</div>
{realName && (
<>
<span aria-hidden="true" className="h-3.5 w-px bg-line-2" />
<span className="text-text-90 typography-body02-regular">
<span aria-hidden="true" className="h-3 w-px bg-line-2" />
<span className="truncate text-text-70 typography-body02-regular">
{realName}
</span>
</>
Expand All @@ -44,12 +49,13 @@ export function ProfileCard({

<button
type="button"
aria-label="프로필 수정"
aria-label="내 정보 수정"
onClick={onEditClick}
className="absolute right-4 top-1/2 flex size-6 -translate-y-1/2 items-center justify-center text-text-90"
className="relative mt-5 flex h-11 w-full items-center justify-center gap-2 rounded-xl border border-main-300 bg-white/90 text-sub transition-colors hover:bg-white active:bg-main-100 typography-body02-semibold"
>
<EditIcon className="size-6 [&_*]:!stroke-current" aria-hidden="true" />
<EditIcon className="size-4 [&_*]:!stroke-current" aria-hidden="true" />
내 정보 수정
</button>
</div>
</section>
)
}
89 changes: 40 additions & 49 deletions src/pages/my/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,49 @@ import { ROUTES } from '@/shared/constants/routes'
import { useUserMe } from '@/features/user/me'
import { ProfileCard } from './components/ProfileCard'
import { MenuListItem } from './components/MenuListItem'
import UserIcon from '@/assets/icons/my/user.svg?react'
import BookmarkIcon from '@/assets/icons/job-lookup-map/Bookmark.svg?react'
import StoreIcon from '@/assets/icons/my/store.svg?react'
import HeadphonesIcon from '@/assets/icons/my/headphones.svg?react'
import FileTextIcon from '@/assets/icons/my/file-text.svg?react'
import SirenIcon from '@/assets/icons/my/siren.svg?react'
import BellIcon from '@/assets/icons/my/bell.svg?react'
import MegaphoneIcon from '@/assets/icons/my/megaphone.svg?react'
import AlertCircleIcon from '@/assets/icons/my/alert-circle.svg?react'

interface MenuItem {
key: string
label: string
description: string
icon: React.ComponentType<React.SVGProps<SVGSVGElement>>
path?: string
path: string
onlyManager?: boolean
onlyWorker?: boolean
}

const MENU_ITEMS: MenuItem[] = [
{ key: 'info', label: '내 정보', icon: UserIcon, path: '/my/info' },
{
key: 'scrapped-postings',
label: '스크랩한 알바',
description: '저장해 둔 채용 공고를 확인해요',
icon: BookmarkIcon,
path: ROUTES.MY.SCRAPPED_POSTINGS,
onlyWorker: true,
},
{
key: 'store-apply',
label: '업장 등록 신청',
description: '신청 현황과 처리 결과를 확인해요',
icon: StoreIcon,
path: ROUTES.STORE_REGISTER.REQUESTS,
},
{
key: 'support',
label: '문의하기',
icon: HeadphonesIcon,
path: '/my/support',
},
{ key: 'faq', label: '자주 묻는 질문', icon: FileTextIcon, path: '/my/faq' },
{ key: 'reports', label: '신고 내역', icon: SirenIcon, path: '/my/reports' },
{
key: 'notifications',
label: '알림 설정',
description: '받고 싶은 알림을 선택해요',
icon: BellIcon,
path: '/my/notifications',
},
{ key: 'notice', label: '공지사항', icon: MegaphoneIcon, path: '/my/notice' },
{
key: 'app-info',
label: '앱 정보',
icon: AlertCircleIcon,
path: '/my/app-info',
path: ROUTES.NOTIFICATION_SETTINGS,
},
]

function MyPageHeader() {
return (
<header className="flex h-14 w-full items-center justify-center border-b border-line-2 bg-bg-light px-4">
<span className="text-text-100 typography-headline03">마이페이지</span>
<header className="flex h-14 w-full items-center bg-white/95 px-5 backdrop-blur">
<h1 className="text-text-100 typography-headline02">마이페이지</h1>
</header>
)
}
Expand Down Expand Up @@ -105,11 +87,11 @@ export function MyPage() {

return (
<div className="flex min-h-[100dvh] flex-col bg-bg-light">
<div className="sticky top-0 z-10 bg-bg-light">
<div className="sticky top-0 z-10 bg-white">
<MyPageHeader />
</div>

<div className="flex flex-1 flex-col px-4 pt-4">
<main className="flex flex-1 flex-col px-4 pb-8 pt-5">
<ProfileCard
nickname={nickname}
realName={realName}
Expand All @@ -135,44 +117,53 @@ export function MyPage() {
</p>
)}

<nav
aria-label="마이페이지 메뉴"
className="mt-3 flex flex-col rounded-2xl"
>
{visibleMenuItems.map((item, index) => (
<MenuListItem
key={item.key}
icon={item.icon}
label={item.label}
isLast={index === visibleMenuItems.length - 1}
onClick={() => item.path && navigate(item.path)}
/>
))}
</nav>
<section className="mt-7">
<h2 className="mb-2 px-1 text-text-70 typography-body02-semibold">
내 활동 및 설정
</h2>
<nav
aria-label="마이페이지 메뉴"
className="overflow-hidden rounded-2xl bg-white shadow-[0_4px_16px_rgba(35,35,35,0.04)]"
>
{visibleMenuItems.map((item, index) => (
<MenuListItem
key={item.key}
icon={item.icon}
label={item.label}
description={item.description}
isLast={index === visibleMenuItems.length - 1}
onClick={() => navigate(item.path)}
/>
))}
</nav>
</section>

{!isManager && (
<p className="mt-2 px-1 typography-body03-regular text-text-70">
승인 완료 후 사장님 계정 전환이 활성화됩니다.
</p>
<div className="mt-3 rounded-xl bg-main-100 px-4 py-3">
<p className="text-sub typography-body03-regular">
업장 등록 승인 후 사장님으로 전환할 수 있어요.
</p>
</div>
)}

<div className="mt-6 flex items-center gap-4 pb-6">
<div className="mt-6 flex items-center justify-center gap-3 text-text-70 typography-body03-regular">
<button
type="button"
onClick={handleLogout}
className="flex h-12 flex-1 items-center justify-center rounded-2xl bg-main text-white typography-body01-regular"
className="rounded-md px-2 py-1 underline-offset-4 hover:text-text-100 hover:underline"
>
로그아웃
</button>
<span aria-hidden="true" className="h-3 w-px bg-line-2" />
<button
type="button"
onClick={handleWithdraw}
className="flex h-12 flex-1 items-center justify-center rounded-2xl bg-white text-text-100 typography-body01-regular"
className="rounded-md px-2 py-1 underline-offset-4 hover:text-error hover:underline"
>
회원 탈퇴
</button>
</div>
</div>
</main>
</div>
)
}
Loading