mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-14 13:13: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,
|
getUrlParams,
|
||||||
setUrlParams,
|
setUrlParams,
|
||||||
} from '../../lib/browser.ts';
|
} 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 = [
|
const groupNames = [
|
||||||
'Absolute Beginners',
|
'Absolute Beginners',
|
||||||
@@ -27,7 +31,7 @@ const groupNames = [
|
|||||||
|
|
||||||
type AllowGroupNames = (typeof groupNames)[number];
|
type AllowGroupNames = (typeof groupNames)[number];
|
||||||
|
|
||||||
type GroupType = {
|
export type GroupType = {
|
||||||
group: AllowGroupNames;
|
group: AllowGroupNames;
|
||||||
roadmaps: {
|
roadmaps: {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -473,6 +477,37 @@ export function RoadmapsPage() {
|
|||||||
]);
|
]);
|
||||||
}, [activeGroup]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
const { g } = getUrlParams() as { g: AllowGroupNames };
|
const { g } = getUrlParams() as { g: AllowGroupNames };
|
||||||
if (!g) {
|
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">
|
<div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3">
|
||||||
{group.roadmaps.map((roadmap) => (
|
{group.roadmaps.map((roadmap) => (
|
||||||
<a
|
<RoadmapCard roadmap={roadmap} key={roadmap.link} />
|
||||||
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>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</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