From 5e5f7427f94d2cab32c3fd96494bc3d01ef6683a Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Mon, 12 Feb 2024 02:21:31 +0600 Subject: [PATCH] fix: user public page --- src/api/user.ts | 30 ++++++- .../UserPublicAccountPage.tsx | 74 ++++++++++++++++ .../UserPublicActivityHeatmap.tsx} | 0 .../UserPublicDetails.tsx} | 10 ++- .../UserPublicProgressStats.tsx | 84 +++++++++++++++++++ src/pages/u/[username]/index.astro | 10 +-- 6 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 src/components/UserPublicAccount/UserPublicAccountPage.tsx rename src/components/{Account/UserActivityHeatmap.tsx => UserPublicAccount/UserPublicActivityHeatmap.tsx} (100%) rename src/components/{Account/UserDetails.tsx => UserPublicAccount/UserPublicDetails.tsx} (78%) create mode 100644 src/components/UserPublicAccount/UserPublicProgressStats.tsx diff --git a/src/api/user.ts b/src/api/user.ts index dc07daeaa..8a677c744 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -38,6 +38,29 @@ export type UserActivityCount = { totalActivityCount: number; }; +type ProgressResponse = { + updatedAt: string; + title: string; + id: string; + learning: number; + skipped: number; + done: number; + total: number; + isCustomResource?: boolean; + roadmapSlug?: string; +}; + +export type UserResourceProgressStats = { + done: { + total: number; + }; + learning: { + total: number; + roadmaps: ProgressResponse[]; + bestPractices: ProgressResponse[]; + }; +}; + export type GetUserByUsernameResponse = Omit< UserDocument, | 'password' @@ -45,9 +68,10 @@ export type GetUserByUsernameResponse = Omit< | 'resetPasswordCode' | 'resetPasswordCodeAt' | 'email' -> & { - activity: UserActivityCount; -}; +> & + UserResourceProgressStats & { + activity: UserActivityCount; + }; export function userApi(context: APIContext) { return { diff --git a/src/components/UserPublicAccount/UserPublicAccountPage.tsx b/src/components/UserPublicAccount/UserPublicAccountPage.tsx new file mode 100644 index 000000000..17df977e4 --- /dev/null +++ b/src/components/UserPublicAccount/UserPublicAccountPage.tsx @@ -0,0 +1,74 @@ +import type { GetUserByUsernameResponse } from '../../api/user'; +import { UserActivityHeatmap } from './UserPublicActivityHeatmap'; +import { UserPublicDetails } from './UserPublicDetails'; +import { UserPublicProgressStats } from './UserPublicProgressStats'; + +type UserPublicAccountPageProps = GetUserByUsernameResponse; + +export function UserPublicAccountPage(props: UserPublicAccountPageProps) { + const { activity, learning } = props; + + const learningRoadmaps = learning?.roadmaps || []; + const learningBestPractices = learning?.bestPractices || []; + + return ( +
+ +
+ +
+ + {(learningRoadmaps.length > 0 || learningBestPractices.length > 0) && ( + <> +

Learning Progress

+
+ {learningRoadmaps + .sort((a, b) => { + const updatedAtA = new Date(a.updatedAt); + const updatedAtB = new Date(b.updatedAt); + + return updatedAtB.getTime() - updatedAtA.getTime(); + }) + .map((roadmap) => ( + + ))} + + {learningBestPractices + .sort((a, b) => { + const updatedAtA = new Date(a.updatedAt); + const updatedAtB = new Date(b.updatedAt); + + return updatedAtB.getTime() - updatedAtA.getTime(); + }) + .map((bestPractice) => ( + + ))} +
+ + )} +
+ ); +} diff --git a/src/components/Account/UserActivityHeatmap.tsx b/src/components/UserPublicAccount/UserPublicActivityHeatmap.tsx similarity index 100% rename from src/components/Account/UserActivityHeatmap.tsx rename to src/components/UserPublicAccount/UserPublicActivityHeatmap.tsx diff --git a/src/components/Account/UserDetails.tsx b/src/components/UserPublicAccount/UserPublicDetails.tsx similarity index 78% rename from src/components/Account/UserDetails.tsx rename to src/components/UserPublicAccount/UserPublicDetails.tsx index 9038a1637..5a32b946d 100644 --- a/src/components/Account/UserDetails.tsx +++ b/src/components/UserPublicAccount/UserPublicDetails.tsx @@ -1,11 +1,11 @@ import { Github, Globe, LinkedinIcon, Twitter } from 'lucide-react'; import type { GetUserByUsernameResponse } from '../../api/user'; -type UserDetailsProps = { +type UserPublicDetailsProps = { userDetails: GetUserByUsernameResponse; }; -export function UserDetails(props: UserDetailsProps) { +export function UserPublicDetails(props: UserPublicDetailsProps) { const { userDetails } = props; const { name, username, links } = userDetails; @@ -20,7 +20,11 @@ export function UserDetails(props: UserDetailsProps) {

{name}

-

@{username}

+

+ I'm a Frontend developer interested in filmmaking, content creation, + vlogging, and backend, currently living in Dhaka, Bangladesh. Right + now I'm writing html at @roadmapsh. Let's grab a coffee. +

diff --git a/src/components/UserPublicAccount/UserPublicProgressStats.tsx b/src/components/UserPublicAccount/UserPublicProgressStats.tsx new file mode 100644 index 000000000..b4b7db79c --- /dev/null +++ b/src/components/UserPublicAccount/UserPublicProgressStats.tsx @@ -0,0 +1,84 @@ +import { getRelativeTimeString } from '../../lib/date'; + +type UserPublicProgressStats = { + resourceType: 'roadmap' | 'best-practice'; + resourceId: string; + title: string; + updatedAt: string; + totalCount: number; + doneCount: number; + learningCount: number; + skippedCount: number; + showClearButton?: boolean; + isCustomResource?: boolean; + roadmapSlug?: string; +}; + +export function UserPublicProgressStats(props: UserPublicProgressStats) { + const { + updatedAt, + resourceType, + resourceId, + title, + totalCount, + learningCount, + doneCount, + skippedCount, + roadmapSlug, + isCustomResource = false, + } = props; + + let url = + resourceType === 'roadmap' + ? `/${resourceId}` + : `/best-practices/${resourceId}`; + + if (isCustomResource) { + url = `/r/${roadmapSlug}`; + } + + const totalMarked = doneCount + skippedCount; + const progressPercentage = Math.round((totalMarked / totalCount) * 100); + + return ( +
+ + + + {title} + + + {getRelativeTimeString(updatedAt)} + + +
+ + {doneCount > 0 && ( + <> + {doneCount} done • + + )} + {learningCount > 0 && ( + <> + {learningCount} in progress • + + )} + {skippedCount > 0 && ( + <> + {skippedCount} skipped • + + )} + {totalCount} total + +
+
+ ); +} diff --git a/src/pages/u/[username]/index.astro b/src/pages/u/[username]/index.astro index fa155226b..a036e709a 100644 --- a/src/pages/u/[username]/index.astro +++ b/src/pages/u/[username]/index.astro @@ -1,6 +1,5 @@ --- -import { UserActivityHeatmap } from '../../../components/Account/UserActivityHeatmap'; -import { UserDetails } from '../../../components/Account/UserDetails'; +import { UserPublicAccountPage } from '../../../components/UserPublicAccount/UserPublicAccountPage'; import { userApi } from '../../../api/user'; import AccountLayout from '../../../layouts/AccountLayout.astro'; @@ -19,10 +18,5 @@ if (error || !userDetails) { --- -
- -
- -
-
+