Update topic done functionality

pull/3813/head
Kamran Ahmed 2 years ago
parent 78e4c38c97
commit 20db0baec5
  1. 18
      src/components/TopicDetail/TopicDetail.tsx
  2. 62
      src/lib/resource-progress.ts

@ -10,9 +10,10 @@ import { httpGet } from '../../lib/http';
import { isLoggedIn } from '../../lib/jwt';
import {
isTopicDone,
renderTopicProgress,
ResourceType,
toggleMarkTopicDone,
} from '../../lib/user-resource-progress';
toggleMarkTopicDone as toggleMarkTopicDoneApi,
} from '../../lib/resource-progress';
import { useKeydown } from '../../hooks/use-keydown';
export function TopicDetail() {
@ -32,22 +33,21 @@ export function TopicDetail() {
const [resourceId, setResourceId] = useState('');
const [resourceType, setResourceType] = useState<ResourceType>('roadmap');
const toggleResourceProgress = (isDone: boolean) => {
const toggleMarkTopicDone = (isDone: boolean) => {
setIsUpdatingProgress(true);
toggleMarkTopicDone({ topicId, resourceId, resourceType }, isDone)
toggleMarkTopicDoneApi({ topicId, resourceId, resourceType }, isDone)
.then(() => {
setIsDone(isDone);
setIsActive(false);
renderTopicProgress(topicId, isDone);
})
.catch(err => {
.catch((err) => {
alert(err.message);
console.error(err);
})
.finally(() => {
setIsUpdatingProgress(false);
});
console.log('toggle', isDone);
};
// Load the topic status when the topic detail is active
@ -168,7 +168,7 @@ export function TopicDetail() {
{!isUpdatingProgress && !isDone && (
<button
className="inline-flex items-center rounded-md border border-green-600 bg-green-600 p-1 px-2 text-sm text-white hover:bg-green-700"
onClick={() => toggleResourceProgress(true)}
onClick={() => toggleMarkTopicDone(true)}
>
<img alt="Check" class="h-4 w-4" src={CheckIcon} />
<span className="ml-2">Mark as Done</span>
@ -178,7 +178,7 @@ export function TopicDetail() {
{!isUpdatingProgress && isDone && (
<button
className="inline-flex items-center rounded-md border border-red-600 bg-red-600 p-1 px-2 text-sm text-white hover:bg-red-700"
onClick={() => toggleResourceProgress(false)}
onClick={() => toggleMarkTopicDone(false)}
>
<img alt="Check" class="h-4" src={ResetIcon} />
<span className="ml-2">Mark as Pending</span>

@ -1,6 +1,7 @@
import { httpGet, httpPatch } from './http';
import Cookies from 'js-cookie';
import { TOKEN_COOKIE_NAME } from './jwt';
import Element = astroHTML.JSX.Element;
export type ResourceType = 'roadmap' | 'best-practice';
@ -12,7 +13,7 @@ type TopicMeta = {
export async function isTopicDone(topic: TopicMeta): Promise<boolean> {
const { topicId, resourceType, resourceId } = topic;
const doneItems = await getUserResourceProgress(resourceType, resourceId);
const doneItems = await getResourceProgress(resourceType, resourceId);
if (!doneItems) {
return false;
@ -41,9 +42,10 @@ export async function toggleMarkTopicDone(
throw new Error(error?.message || 'Something went wrong');
}
setUserResourceProgress(resourceType, resourceId, response.done);
setResourceProgress(resourceType, resourceId, response.done);
}
export async function getUserResourceProgress(
export async function getResourceProgress(
resourceType: 'roadmap' | 'best-practice',
resourceId: string
): Promise<string[]> {
@ -92,12 +94,12 @@ async function loadFreshProgress(
return [];
}
setUserResourceProgress(resourceType, resourceId, response.done);
setResourceProgress(resourceType, resourceId, response.done);
return response.done;
}
export function setUserResourceProgress(
export function setResourceProgress(
resourceType: 'roadmap' | 'best-practice',
resourceId: string,
done: string[]
@ -110,3 +112,53 @@ export function setUserResourceProgress(
})
);
}
export function renderTopicProgress(topicId: string, isDone: boolean) {
const matchingElements: Element[] = [];
// Elements having sort order in the beginning of the group id
document
.querySelectorAll(`[data-group-id$="-${topicId}"]`)
.forEach((element: unknown) => {
const foundGroupId =
(element as HTMLOrSVGElement)?.dataset?.groupId || '';
const validGroupRegex = new RegExp(`^\\d+-${topicId}$`);
if (validGroupRegex.test(foundGroupId)) {
matchingElements.push(element);
}
});
// Elements with exact match of the topic id
document
.querySelectorAll(`[data-group-id="${topicId}"]`)
.forEach((element) => {
matchingElements.push(element);
});
// Matching "check:XXXX" box of the topic
document
.querySelectorAll(`[data-group-id="check:${topicId}"]`)
.forEach((element) => {
matchingElements.push(element);
});
matchingElements.forEach((element) => {
if (isDone) {
element.classList.add('done');
} else {
element.classList.remove('done');
}
});
}
export async function renderResourceProgress(
resourceType: ResourceType,
resourceId: string
) {
const progress = await getResourceProgress(resourceType, resourceId);
progress.forEach((topicId) => {
renderTopicProgress(topicId, true);
});
}
Loading…
Cancel
Save