mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-13 12:43:59 +02:00
feat: add mark favourite button (#7156)
* feat: add mark favourite button * fix: update favourite
This commit is contained in:
31
src/components/Roadmaps/RoadmapCard.tsx
Normal file
31
src/components/Roadmaps/RoadmapCard.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useIsMounted } from '../../hooks/use-is-mounted';
|
||||
import { MarkFavorite } from '../FeaturedItems/MarkFavorite';
|
||||
import type { GroupType } from './RoadmapsPage';
|
||||
|
||||
type RoadmapCardProps = {
|
||||
roadmap: GroupType['roadmaps'][number];
|
||||
};
|
||||
|
||||
export function RoadmapCard(props: RoadmapCardProps) {
|
||||
const { roadmap } = props;
|
||||
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
return (
|
||||
<a
|
||||
key={roadmap.link}
|
||||
className="relative rounded-md border bg-white px-3 py-2 text-left text-sm shadow-sm transition-all hover:border-gray-300 hover:bg-gray-50"
|
||||
href={roadmap.link}
|
||||
>
|
||||
{roadmap.title}
|
||||
|
||||
{isMounted && (
|
||||
<MarkFavorite
|
||||
resourceId={roadmap.link.split('/').pop()!}
|
||||
resourceType="roadmap"
|
||||
className="data-[is-favorite=true]:opacity-35"
|
||||
/>
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
}
|
@@ -8,6 +8,10 @@ import {
|
||||
getUrlParams,
|
||||
setUrlParams,
|
||||
} from '../../lib/browser.ts';
|
||||
import { RoadmapCard } from './RoadmapCard.tsx';
|
||||
import { httpGet } from '../../lib/http.ts';
|
||||
import type { UserProgressResponse } from '../HeroSection/FavoriteRoadmaps.tsx';
|
||||
import { isLoggedIn } from '../../lib/jwt.ts';
|
||||
|
||||
const groupNames = [
|
||||
'Absolute Beginners',
|
||||
@@ -27,7 +31,7 @@ const groupNames = [
|
||||
|
||||
type AllowGroupNames = (typeof groupNames)[number];
|
||||
|
||||
type GroupType = {
|
||||
export type GroupType = {
|
||||
group: AllowGroupNames;
|
||||
roadmaps: {
|
||||
title: string;
|
||||
@@ -473,6 +477,37 @@ export function RoadmapsPage() {
|
||||
]);
|
||||
}, [activeGroup]);
|
||||
|
||||
async function loadProgress() {
|
||||
const { response: progressList, error } =
|
||||
await httpGet<UserProgressResponse>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-get-hero-roadmaps`,
|
||||
);
|
||||
|
||||
if (error || !progressList) {
|
||||
return;
|
||||
}
|
||||
|
||||
progressList?.forEach((progress) => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('mark-favorite', {
|
||||
detail: {
|
||||
resourceId: progress.resourceId,
|
||||
resourceType: progress.resourceType,
|
||||
isFavorite: progress.isFavorite,
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoggedIn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadProgress().finally(() => {});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const { g } = getUrlParams() as { g: AllowGroupNames };
|
||||
if (!g) {
|
||||
@@ -547,13 +582,7 @@ export function RoadmapsPage() {
|
||||
|
||||
<div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3">
|
||||
{group.roadmaps.map((roadmap) => (
|
||||
<a
|
||||
key={roadmap.link}
|
||||
className="rounded-md border bg-white px-3 py-2 text-left text-sm shadow-sm transition-all hover:border-gray-300 hover:bg-gray-50"
|
||||
href={roadmap.link}
|
||||
>
|
||||
{roadmap.title}
|
||||
</a>
|
||||
<RoadmapCard roadmap={roadmap} key={roadmap.link} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
13
src/hooks/use-is-mounted.ts
Normal file
13
src/hooks/use-is-mounted.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function useIsMounted() {
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
|
||||
return () => {
|
||||
setIsMounted(false);
|
||||
};
|
||||
}, []);
|
||||
return isMounted;
|
||||
}
|
Reference in New Issue
Block a user