wip: add resource api

feat/resources
Arik Chakma 3 months ago
parent 447bf4eb0f
commit a2440f31ec
  1. 62
      src/components/TopicDetail/TopicDetail.tsx

@ -32,6 +32,18 @@ import { YouTubeIcon } from '../ReactIcons/YouTubeIcon.tsx';
import { resourceTitleFromId } from '../../lib/roadmap.ts';
import { lockBodyScroll } from '../../lib/dom.ts';
export const allowedRoadmapResourceTypes = ['course', 'book', 'other'] as const;
export type AllowedRoadmapResourceType =
(typeof allowedRoadmapResourceTypes)[number];
type TopicResource = {
_id?: string;
title: string;
type: AllowedRoadmapResourceType;
url: string;
topicIds: string[];
};
type TopicDetailProps = {
resourceTitle?: string;
resourceType?: ResourceType;
@ -50,7 +62,7 @@ const linkTypes: Record<AllowedLinkTypes, string> = {
video: 'bg-purple-300',
website: 'bg-blue-300',
official: 'bg-blue-600 text-white',
feed: "bg-[#ce3df3] text-white"
feed: 'bg-[#ce3df3] text-white',
};
export function TopicDetail(props: TopicDetailProps) {
@ -69,6 +81,8 @@ export function TopicDetail(props: TopicDetailProps) {
const [links, setLinks] = useState<RoadmapContentDocument['links']>([]);
const toast = useToast();
const [topicResources, setTopicResources] = useState<TopicResource[]>([]);
const { secret } = getUrlParams() as { secret: string };
const isGuest = useMemo(() => !isLoggedIn(), []);
const topicRef = useRef<HTMLDivElement>(null);
@ -87,6 +101,20 @@ export function TopicDetail(props: TopicDetailProps) {
setIsActive(false);
});
const loadTopicResources = async (roadmapId: string, topicId: string) => {
const sanitizedTopicId = topicId.split('@')?.[1] || topicId;
const { response, error } = await httpGet<TopicResource[]>(
`${import.meta.env.PUBLIC_API_URL}/v1-list-topic-resources/${roadmapId}?t=${sanitizedTopicId}`,
);
if (error) {
toast.error(error?.message || 'Failed to load topic resources');
return;
}
setTopicResources(response || []);
};
// Toggle topic is available even if the component UI is not active
// This is used on the best practice screen where we have the checkboxes
// to mark the topic as done/undone.
@ -151,6 +179,7 @@ export function TopicDetail(props: TopicDetailProps) {
}`;
}
Promise.all([
httpGet<string | RoadmapContentDocument>(
topicUrl,
{},
@ -181,7 +210,9 @@ export function TopicDetail(props: TopicDetailProps) {
const contributionUrl = urlElem?.dataset?.githubUrl || '';
const titleElem: HTMLElement = topicDom.querySelector('h1')!;
const otherElems = topicDom.querySelectorAll('body > *:not(h1, div)');
const otherElems = topicDom.querySelectorAll(
'body > *:not(h1, div)',
);
let ulWithLinks: HTMLUListElement = document.createElement('ul');
@ -225,7 +256,13 @@ export function TopicDetail(props: TopicDetailProps) {
// article at third
// videos at fourth
// rest at last
const order = ['official', 'opensource', 'article', 'video', 'feed'];
const order = [
'official',
'opensource',
'article',
'video',
'feed',
];
return order.indexOf(a.type) - order.indexOf(b.type);
});
@ -258,7 +295,9 @@ export function TopicDetail(props: TopicDetailProps) {
.catch((err) => {
setError('Something went wrong. Please try again later.');
setIsLoading(false);
});
}),
loadTopicResources(resourceId, topicId),
]);
});
useEffect(() => {
@ -424,11 +463,15 @@ export function TopicDetail(props: TopicDetailProps) {
)}
{/* Contribution */}
{canSubmitContribution && !hasEnoughLinks && contributionUrl && hasContent && (
{canSubmitContribution &&
!hasEnoughLinks &&
contributionUrl &&
hasContent && (
<div className="mb-12 mt-3 border-t text-sm text-gray-400 sm:mt-12">
<div className="mb-4 mt-3">
<p className="">
Find more resources using these pre-filled search queries:
Find more resources using these pre-filled search
queries:
</p>
<div className="mt-3 flex gap-2 text-gray-700">
<a
@ -451,9 +494,10 @@ export function TopicDetail(props: TopicDetailProps) {
</div>
<p className="mb-2 mt-2 leading-relaxed">
This popup should be a brief introductory paragraph for the topic and a few links
to good articles, videos, or any other self-vetted resources. Please consider
submitting a PR to improve this content.
This popup should be a brief introductory paragraph for
the topic and a few links to good articles, videos, or any
other self-vetted resources. Please consider submitting a
PR to improve this content.
</p>
<a
href={contributionUrl}

Loading…
Cancel
Save