diff --git a/src/components/CustomRoadmap/CustomRoadmapRatingsModal.tsx b/src/components/CustomRoadmap/CustomRoadmapRatingsModal.tsx index 75dfdc177..f0c5f5812 100644 --- a/src/components/CustomRoadmap/CustomRoadmapRatingsModal.tsx +++ b/src/components/CustomRoadmap/CustomRoadmapRatingsModal.tsx @@ -21,7 +21,10 @@ export function CustomRoadmapRatingsModal( ) { const { onClose, ratings, roadmapSlug, canManage = false } = props; - const [activeTab, setActiveTab] = useState('ratings'); + const [activeTab, setActiveTab] = useState( + canManage ? 'feedback' : 'ratings', + ); + const tabs: { id: ActiveTab; label: string; @@ -38,36 +41,38 @@ export function CustomRoadmapRatingsModal( return ( - {canManage && ( -
- {tabs.map((tab) => { - const isActive = tab.id === activeTab; + {/*{canManage && (*/} + {/*
*/} + {/* {tabs.map((tab) => {*/} + {/* const isActive = tab.id === activeTab;*/} - return ( - - ); - })} -
- )} + {/* return (*/} + {/* {*/} + {/* setActiveTab(tab.id);*/} + {/* }}*/} + {/* className={cn('rounded-md bg-white px-3 py-2 text-sm', {*/} + {/* 'bg-gray-100 font-medium text-black': isActive,*/} + {/* 'text-gray-500 hover:text-gray-700': !isActive,*/} + {/* })}*/} + {/* >*/} + {/* {tab.label}*/} + {/* */} + {/* );*/} + {/* })}*/} + {/*
*/} + {/*)}*/} {activeTab === 'ratings' && ( - + )} {activeTab === 'feedback' && ( - + )}
); diff --git a/src/components/CustomRoadmap/ListRoadmapRatings.tsx b/src/components/CustomRoadmap/ListRoadmapRatings.tsx index 90ccdb023..fb0e990d0 100644 --- a/src/components/CustomRoadmap/ListRoadmapRatings.tsx +++ b/src/components/CustomRoadmap/ListRoadmapRatings.tsx @@ -4,6 +4,10 @@ import { useToast } from '../../hooks/use-toast'; import { isLoggedIn } from '../../lib/jwt'; import { Loader2, MessageCircle, ServerCrash } from 'lucide-react'; import { Rating } from '../Rating/Rating'; +import { Spinner } from '../ReactIcons/Spinner.tsx'; +import { getRelativeTimeString } from '../../lib/date.ts'; +import { cn } from '../../lib/classname.ts'; +import type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal.tsx'; export interface RoadmapRatingDocument { _id?: string; @@ -23,12 +27,18 @@ type ListRoadmapRatingsResponse = (RoadmapRatingDocument & { type ListRoadmapRatingsProps = { roadmapSlug: string; + ratings: RoadmapDocument['ratings']; }; export function ListRoadmapRatings(props: ListRoadmapRatingsProps) { - const { roadmapSlug } = props; + const { roadmapSlug, ratings: ratingSummary } = props; + + const totalWhoRated = Object.keys(ratingSummary.breakdown || {}).reduce( + (acc, key) => acc + ratingSummary.breakdown[key as any], + 0, + ); + const averageRating = ratingSummary.average; - const toast = useToast(); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(''); const [ratings, setRatings] = useState([]); @@ -59,7 +69,7 @@ export function ListRoadmapRatings(props: ListRoadmapRatingsProps) { if (error) { return ( -
+

{error}

@@ -67,41 +77,64 @@ export function ListRoadmapRatings(props: ListRoadmapRatingsProps) { } return ( -
+
{isLoading && ( -
- +
+
)} {!isLoading && ratings.length > 0 && ( -
- {ratings.map((rating) => { - const userAvatar = rating?.avatar - ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${rating.avatar}` - : '/images/default-avatar.png'; - - return ( -
-
- {rating.name} - {rating.name} -
- -
- - - {rating.feedback && ( -

{rating.feedback}

- )} +
+
+ Rated {averageRating.toFixed(1)} + + by {totalWhoRated} user{totalWhoRated > 1 && 's'} +
+ +
+ {ratings.map((rating) => { + const userAvatar = rating?.avatar + ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${rating.avatar}` + : '/images/default-avatar.png'; + + const isLastRating = + ratings[ratings.length - 1]._id === rating._id; + + return ( +
+
+
+ {rating.name} + {rating.name} +
+ + {getRelativeTimeString(rating.createdAt)} + +
+ +
+ + + {rating.feedback && ( +

+ {rating.feedback} +

+ )} +
-
- ); - })} + ); + })} +
)} diff --git a/src/components/CustomRoadmap/RateRoadmapForm.tsx b/src/components/CustomRoadmap/RateRoadmapForm.tsx index 68363d667..4e93a3ef7 100644 --- a/src/components/CustomRoadmap/RateRoadmapForm.tsx +++ b/src/components/CustomRoadmap/RateRoadmapForm.tsx @@ -107,7 +107,7 @@ export function RateRoadmapForm(props: RateRoadmapFormProps) {
{showRatingsBreakdown && !isRatingRoadmap && ( <> -
    +
      {ratingsKeys.map((rating) => { const percentage = totalRatings <= 0 @@ -134,7 +134,7 @@ export function RateRoadmapForm(props: RateRoadmapFormProps) {
- {percentage}% + {parseInt(`${percentage}`, 10)}% ); diff --git a/src/components/CustomRoadmap/SkeletonRoadmapHeader.tsx b/src/components/CustomRoadmap/SkeletonRoadmapHeader.tsx index 6b2b4ff69..e0d9bd14d 100644 --- a/src/components/CustomRoadmap/SkeletonRoadmapHeader.tsx +++ b/src/components/CustomRoadmap/SkeletonRoadmapHeader.tsx @@ -17,9 +17,8 @@ export function SkeletonRoadmapHeader() {
-
-
-
+
+
diff --git a/src/lib/date.ts b/src/lib/date.ts index 170981833..0316c2ca4 100644 --- a/src/lib/date.ts +++ b/src/lib/date.ts @@ -1,11 +1,11 @@ import dayjs from 'dayjs'; export function getRelativeTimeString( - date: string, + date: string | Date, isTimed: boolean = false, ): string { if (!Intl?.RelativeTimeFormat) { - return date; + return date.toString(); } const rtf = new Intl.RelativeTimeFormat('en', {