-
Notifications
You must be signed in to change notification settings - Fork 1
✨ feat: 프로필(/profile) 페이지 구현 #68
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
Merged
Merged
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
0cf9c37
✨ feat: profile type, constant 추가
junyeokk 5c27958
✨ feat: profile header 컴포넌트 추가
junyeokk 4a087b0
✨ feat: profile sidebar 컴포넌트 추가
junyeokk a5e77f8
✨ feat: profile section 컴포넌트 추가
junyeokk 93ef094
✨ feat: profile 페이지, 라우팅 추가
junyeokk 02fc23d
♻️ refactor: 프로필 클릭 시 맨 위로 스크롤 되지 않는 현상 해결
junyeokk 377d2e5
✨ feat: activity 컴포넌트 관련 타입 추가
junyeokk c4374c8
✨ feat: activity 컴포넌트 Mock 수정
junyeokk 3a61af6
✨ feat: activity 컴포넌트 추가
junyeokk 570b31b
📦 chore: lodash 의존성 추가
junyeokk f1c9bfa
✨ feat: pipe로 데이터 변환 로직 개선 및 그리드 날짜 정렬
junyeokk 894f81f
♻️ refactor: activity mock data 생성 방식 수정
junyeokk dc138bd
♻️ refactor: activity 순수 함수, pipeline, 컴포넌트 분리
junyeokk d18f7b5
Merge branch 'main' of https://github.com/boostcampwm-2024/refactor-w…
junyeokk 410f45e
♻️ refactor: dayCell tooltip hover 시 duration 200ms로 변경 및 UX 향상
junyeokk d35359a
Merge branch 'main' into feat/profile-page
junyeokk 884739a
♻️ refactor: profile 컴포넌트 import 상대 경로 였던 부분들 모두 절대 경로로 변경
junyeokk 6bfbd8f
Merge branch 'feat/profile-page' of https://github.com/boostcampwm-20…
junyeokk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Card, CardContent } from "@/components/ui/card.tsx"; | ||
|
||
interface ProfileTempSectionProps { | ||
title: string; | ||
} | ||
|
||
export const Section = ({ title }: ProfileTempSectionProps) => { | ||
return ( | ||
<Card className="mb-8 overflow-hidden"> | ||
<CardContent className="p-6 h-96"> | ||
<h3 className="text-lg font-semibold mb-4">{title}</h3> | ||
<p className="text-gray-400">서비스가 현재 개발 중입니다. 곧 만나요!</p> | ||
</CardContent> | ||
</Card> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Card, CardContent } from "@/components/ui/card.tsx"; | ||
|
||
import { Avatar, Banner, Info, Stats } from "./index"; | ||
import { ActivityGraph } from "./ui/ActivityGraph/ActivityGraph.tsx"; | ||
import { User } from "@/types/profile.ts"; | ||
|
||
interface ProfileHeaderProps { | ||
user: User; | ||
} | ||
|
||
export const Header = ({ user }: ProfileHeaderProps) => { | ||
return ( | ||
<Card className="mb-8 overflow-hidden"> | ||
{user.rssRegistered && <Banner lastPosted={user.lastPosted} />} | ||
|
||
<CardContent className="p-6"> | ||
<div className="flex items-start justify-between"> | ||
<div className="flex space-x-6"> | ||
<Avatar user={user} /> | ||
<Info user={user} /> | ||
</div> | ||
</div> | ||
<Stats totalPosts={user.totalPosts} totalViews={user.totalViews} topicsCount={user.topics.length} /> | ||
<div className="mt-6"> | ||
<ActivityGraph dailyActivities={user.dailyActivities} /> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from "./ui/Avatar"; | ||
export * from "./ui/Banner"; | ||
export * from "./ui/Info"; | ||
export * from "./ui/Stats"; |
38 changes: 38 additions & 0 deletions
38
client/src/components/profile/header/ui/ActivityGraph/ActivityGraph.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { TooltipProvider } from "@/components/ui/tooltip.tsx"; | ||
|
||
import { processActivityData } from "@/utils/activity.ts"; | ||
|
||
import { DayLabels } from "./DayLabels.tsx"; | ||
import { Legend } from "./Legend.tsx"; | ||
import { MonthLabels } from "./MonthLabels.tsx"; | ||
import { Week } from "./Week.tsx"; | ||
import { DailyActivity } from "@/types/profile.ts"; | ||
|
||
interface ActivityGraphProps { | ||
dailyActivities: DailyActivity[]; | ||
} | ||
|
||
export const ActivityGraph = ({ dailyActivities }: ActivityGraphProps) => { | ||
const today = new Date(); | ||
const { weeks } = processActivityData(dailyActivities, today); | ||
|
||
return ( | ||
<div className="p-4 bg-white rounded-lg"> | ||
<h3 className="text-lg font-semibold mb-4">Activity</h3> | ||
<TooltipProvider> | ||
jungmyunggi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<div className="flex flex-col"> | ||
<MonthLabels weeks={weeks} /> | ||
<div className="flex"> | ||
<DayLabels /> | ||
<div className="flex gap-0.5"> | ||
{weeks.map((weekInfo) => ( | ||
<Week key={weekInfo.weekNumber} weekInfo={weekInfo} /> | ||
))} | ||
</div> | ||
</div> | ||
</div> | ||
</TooltipProvider> | ||
<Legend /> | ||
</div> | ||
); | ||
}; |
16 changes: 16 additions & 0 deletions
16
client/src/components/profile/header/ui/ActivityGraph/DayCell.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip.tsx"; | ||
|
||
import { getColorClass } from "@/utils/color.ts"; | ||
|
||
import { DayInfo } from "@/types/activity.ts"; | ||
|
||
export const DayCell = ({ dayInfo }: { dayInfo: DayInfo }) => ( | ||
<Tooltip> | ||
<TooltipTrigger> | ||
<div className={`w-2.5 h-2.5 rounded-sm ${getColorClass(dayInfo.count)}`} /> | ||
</TooltipTrigger> | ||
<TooltipContent> | ||
<p>{`${dayInfo.dateStr}: ${dayInfo.count} views`}</p> | ||
</TooltipContent> | ||
</Tooltip> | ||
); |
7 changes: 7 additions & 0 deletions
7
client/src/components/profile/header/ui/ActivityGraph/DayLabels.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const DayLabels = () => ( | ||
<div className="flex flex-col justify-between text-xs text-gray-400 pr-2"> | ||
<span className="translate-y-2">Mon</span> | ||
<span>Wed</span> | ||
<span className="-translate-y-2">Fri</span> | ||
</div> | ||
); |
13 changes: 13 additions & 0 deletions
13
client/src/components/profile/header/ui/ActivityGraph/Legend.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export const Legend = () => ( | ||
<div className="mt-4 flex items-center text-xs text-gray-500 space-x-2"> | ||
<span>Less</span> | ||
<div className="flex space-x-0.5"> | ||
<div className="w-3 h-3 bg-gray-100 rounded-sm" /> | ||
<div className="w-3 h-3 bg-green-200 rounded-sm" /> | ||
<div className="w-3 h-3 bg-green-300 rounded-sm" /> | ||
<div className="w-3 h-3 bg-green-400 rounded-sm" /> | ||
<div className="w-3 h-3 bg-green-500 rounded-sm" /> | ||
</div> | ||
<span>More</span> | ||
</div> | ||
); |
31 changes: 31 additions & 0 deletions
31
client/src/components/profile/header/ui/ActivityGraph/MonthLabels.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { WeekInfo } from "@/types/activity.ts"; | ||
|
||
export const MonthLabels = ({ weeks }: { weeks: WeekInfo[] }) => { | ||
const monthPositions = weeks.reduce( | ||
(acc, week, index) => { | ||
const firstDayOfWeek = week.days[0]; | ||
const month = firstDayOfWeek.date.toLocaleString("en-US", { month: "short" }); | ||
|
||
if (index === 0 || month !== weeks[index - 1].days[0].date.toLocaleString("en-US", { month: "short" })) { | ||
acc.push({ | ||
month, | ||
position: `${index * 0.75}rem`, | ||
}); | ||
} | ||
return acc; | ||
}, | ||
[] as Array<{ month: string; position: string }> | ||
); | ||
|
||
return ( | ||
<div className="flex mb-5 pl-6"> | ||
<div className="relative flex"> | ||
{monthPositions.map(({ month, position }, index) => ( | ||
<div key={`${month}-${index}`} className="absolute text-xs text-gray-400" style={{ left: position }}> | ||
{month} | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; |
10 changes: 10 additions & 0 deletions
10
client/src/components/profile/header/ui/ActivityGraph/Week.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { DayCell } from "./DayCell.tsx"; | ||
import { WeekInfo } from "@/types/activity.ts"; | ||
|
||
export const Week = ({ weekInfo }: { weekInfo: WeekInfo }) => ( | ||
<div className="grid grid-rows-7 gap-0.5"> | ||
{weekInfo.days.map((day) => ( | ||
<DayCell key={day.dateStr} dayInfo={day} /> | ||
))} | ||
</div> | ||
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { CheckCircle2 } from "lucide-react"; | ||
|
||
import { Avatar as AvatarUI, AvatarFallback, AvatarImage } from "@/components/ui/avatar.tsx"; | ||
|
||
import { User } from "@/types/profile.ts"; | ||
|
||
interface ProfileHeaderAvatarProps { | ||
user: User; | ||
} | ||
|
||
export const Avatar = ({ user }: ProfileHeaderAvatarProps) => { | ||
return ( | ||
<div className="relative w-24 h-24"> | ||
<AvatarUI className="w-24 h-24 border-4 border-white"> | ||
<AvatarImage src={user.avatar} /> | ||
<AvatarFallback>KD</AvatarFallback> | ||
</AvatarUI> | ||
{user.rssRegistered && ( | ||
<div className="absolute -bottom-2 -right-2 bg-white rounded-full p-1 shadow-md"> | ||
<CheckCircle2 className="w-5 h-5 text-blue-500" /> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { CheckCircle2 } from "lucide-react"; | ||
|
||
interface ProfileHeaderBannerProps { | ||
lastPosted: string; | ||
} | ||
|
||
export const Banner = ({ lastPosted }: ProfileHeaderBannerProps) => { | ||
return ( | ||
<div className="bg-blue-500 px-6 py-2 text-white flex items-center justify-between"> | ||
<div className="flex items-center space-x-2"> | ||
<CheckCircle2 className="w-5 h-5" /> | ||
<span>인증된 RSS 블로거</span> | ||
</div> | ||
<span className="text-sm">마지막 포스팅: {lastPosted}</span> | ||
</div> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Edit } from "lucide-react"; | ||
|
||
import { Badge } from "@/components/ui/badge.tsx"; | ||
import { Button } from "@/components/ui/button.tsx"; | ||
|
||
import { User } from "@/types/profile.ts"; | ||
|
||
interface ProfileHeaderInfoProps { | ||
user: User; | ||
} | ||
|
||
export const Info = ({ user }: ProfileHeaderInfoProps) => { | ||
return ( | ||
<div> | ||
<div className="flex items-center space-x-4"> | ||
<h1 className="text-2xl font-bold">{user.name}</h1> | ||
<Button variant="outline" size="sm" className="flex items-center"> | ||
<Edit className="w-4 h-4 mr-2" /> | ||
프로필 수정 | ||
</Button> | ||
</div> | ||
<p className="text-gray-600 mt-1">{user.email}</p> | ||
{user.blogUrl && ( | ||
<a href={user.blogUrl} target="_blank" rel="noopener noreferrer" className="text-blue-600 mt-2 hover:underline"> | ||
{user.blogUrl} | ||
</a> | ||
)} | ||
<p className="text-gray-800 mt-4">{user.bio}</p> | ||
<div className="flex flex-wrap gap-2 mt-4"> | ||
{user.topics.map((topic) => ( | ||
<Badge key={topic} variant="secondary"> | ||
{topic} | ||
</Badge> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
interface ProfileStatsProps { | ||
totalPosts: number; | ||
totalViews: number; | ||
topicsCount: number; | ||
} | ||
|
||
export const Stats = ({ totalPosts, totalViews, topicsCount }: ProfileStatsProps) => { | ||
return ( | ||
<div className="grid grid-cols-3 gap-4 mt-8 p-4 bg-gray-50 rounded-lg"> | ||
<div className="text-center"> | ||
<p className="text-2xl font-bold text-blue-600">{totalPosts}</p> | ||
<p className="text-sm text-gray-600">총 포스팅</p> | ||
</div> | ||
<div className="text-center border-l border-r border-gray-200"> | ||
<p className="text-2xl font-bold text-blue-600">{totalViews.toLocaleString()}</p> | ||
<p className="text-sm text-gray-600">월간 조회수</p> | ||
</div> | ||
<div className="text-center"> | ||
<p className="text-2xl font-bold text-blue-600">{topicsCount}</p> | ||
<p className="text-sm text-gray-600">관심 토픽</p> | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Section } from "../common/Section.tsx"; | ||
|
||
export const LikedPosts = () => { | ||
return ( | ||
<section id="liked-posts"> | ||
<Section title="좋아요한 목록" /> | ||
</section> | ||
); | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.