diff --git a/frontend/src/pages/Workspace/ui/WorkspacePage.tsx b/frontend/src/pages/Workspace/ui/WorkspacePage.tsx index adb7dd89..3b964b3b 100644 --- a/frontend/src/pages/Workspace/ui/WorkspacePage.tsx +++ b/frontend/src/pages/Workspace/ui/WorkspacePage.tsx @@ -1,51 +1,53 @@ -import { useAuth, useLogout } from '@/features/auth' +import { SiteNav } from '@/widgets/site-nav' +import { SiteFooter } from '@/widgets/site-footer' +import { WorkspaceProfileCard } from '@/widgets/workspace-profile-card' +import { WorkspaceSection } from '@/widgets/workspace-section' +//이 컴포넌트는 아직 초기 프로토타입 입니다. export default function WorkspacePage() { - const { user } = useAuth() - const { logout, loggingOut } = useLogout() - return ( -
-

Workspace

-

이력서·레포 관리 화면이 들어갈 자리입니다.

+
+ +
+ + + + + - {user ? ( -
- {user.avatarUrl ? ( - {user.githubUsername} - ) : null} -
-
- @{user.githubUsername} -
-
- {user.email ?? 'email 없음'} -
-
-
- ) : null} + + +
+ +
+ ) +} -
- -
-
+function EmptyResumeSlot() { + return ( +
+

아직 등록된 이력서가 없습니다.

+

+ 다음 단계에서 PDF 업로드가 가능해집니다. +

+
+ ) +} + +function EmptyRepoSlot() { + return ( +
+

아직 등록된 레포지토리가 없습니다.

+

+ 다음 단계에서 GitHub 레포 가져오기가 가능해집니다. +

+
) } diff --git a/frontend/src/widgets/CLAUDE.md b/frontend/src/widgets/CLAUDE.md index 8885e7b5..ad23c576 100644 --- a/frontend/src/widgets/CLAUDE.md +++ b/frontend/src/widgets/CLAUDE.md @@ -75,7 +75,7 @@ widgets/{X} → pages/*, app/* ✗ |---|---|---| | `site-*` | 사이트 전역 (여러 페이지 재사용) | `site-nav`, `site-footer` | | `home-*` | 홈페이지 전용 | `home-hero`, `home-services`, `home-faq` | -| `workspace-*` (예정) | 워크스페이스 페이지 전용 | `workspace-sidebar` | +| `workspace-*` | 워크스페이스 페이지 전용 | `workspace-profile-card`, `workspace-section` | | `interview-*` (예정) | 면접 페이지 전용 | `interview-control`, `interview-transcript` | > prefix 가 페이지 종속을 명시적으로 표현. 한 페이지에서만 쓰이는 widget 도 정상. @@ -93,6 +93,8 @@ widgets/{X} → pages/*, app/* ✗ | `home-quote` | 다크 그린 quote · 팀 크레딧 | `/` | | `home-faq` | FAQ 아코디언 (`
` 기반) | `/` | | `home-cta` | 풀-블리드 CTA 배너 | `/` | +| `workspace-profile-card` | `useAuth().user` 기반 프로필 카드 (avatar + 핸들 + email + 연결 상태) | `/workspace` | +| `workspace-section` | 타이틀·설명·우측 액션·children 슬롯 컨테이너 (도메인 무관) | `/workspace` | --- diff --git a/frontend/src/widgets/workspace-profile-card/index.ts b/frontend/src/widgets/workspace-profile-card/index.ts new file mode 100644 index 00000000..4f004789 --- /dev/null +++ b/frontend/src/widgets/workspace-profile-card/index.ts @@ -0,0 +1 @@ +export { WorkspaceProfileCard } from './ui/WorkspaceProfileCard' diff --git a/frontend/src/widgets/workspace-profile-card/ui/WorkspaceProfileCard.tsx b/frontend/src/widgets/workspace-profile-card/ui/WorkspaceProfileCard.tsx new file mode 100644 index 00000000..77754f28 --- /dev/null +++ b/frontend/src/widgets/workspace-profile-card/ui/WorkspaceProfileCard.tsx @@ -0,0 +1,79 @@ +import { useAuth } from '@/features/auth' + +export function WorkspaceProfileCard() { + const { status, user } = useAuth() + + if (status === 'loading') return + if (!user) return null + + return ( +
+ +
+

+ @{user.githubUsername} +

+

+ {user.email ?? '이메일 미공개'} +

+

+ + GitHub로 연결됨 +

+
+
+ ) +} + +function Avatar({ url, name }: { url: string | null; name: string }) { + if (url) { + return ( + {name} + ) + } + const initial = name.charAt(0).toUpperCase() || '?' + return ( +
+ {initial} +
+ ) +} + +function GithubMark() { + return ( + + + + ) +} + +function ProfileSkeleton() { + return ( +
+
+
+
+
+
+
+ ) +} diff --git a/frontend/src/widgets/workspace-section/index.ts b/frontend/src/widgets/workspace-section/index.ts new file mode 100644 index 00000000..29ea2cc9 --- /dev/null +++ b/frontend/src/widgets/workspace-section/index.ts @@ -0,0 +1 @@ +export { WorkspaceSection } from './ui/WorkspaceSection' diff --git a/frontend/src/widgets/workspace-section/ui/WorkspaceSection.tsx b/frontend/src/widgets/workspace-section/ui/WorkspaceSection.tsx new file mode 100644 index 00000000..83ea2af0 --- /dev/null +++ b/frontend/src/widgets/workspace-section/ui/WorkspaceSection.tsx @@ -0,0 +1,33 @@ +import type { ReactNode } from 'react' + +//단순 위젯 수준은 model분리를 추후에 분리를 고려합니다. +type Props = { + title: string + description?: string + action?: ReactNode + children: ReactNode +} + +export function WorkspaceSection({ + title, + description, + action, + children, +}: Props) { + return ( +
+
+
+

+ {title} +

+ {description ? ( +

{description}

+ ) : null} +
+ {action} +
+ {children} +
+ ) +}