|
|
|
@ -4,7 +4,7 @@ import { TOKEN_COOKIE_NAME } from './jwt'; |
|
|
|
|
import Element = astroHTML.JSX.Element; |
|
|
|
|
|
|
|
|
|
export type ResourceType = 'roadmap' | 'best-practice'; |
|
|
|
|
export type ResourceProgressType = 'done' | 'learning' | 'pending'; |
|
|
|
|
export type ResourceProgressType = 'done' | 'learning' | 'pending' | 'skipped'; |
|
|
|
|
|
|
|
|
|
type TopicMeta = { |
|
|
|
|
topicId: string; |
|
|
|
@ -26,14 +26,18 @@ export async function getTopicStatus( |
|
|
|
|
const { topicId, resourceType, resourceId } = topic; |
|
|
|
|
const progressResult = await getResourceProgress(resourceType, resourceId); |
|
|
|
|
|
|
|
|
|
if (progressResult?.done.includes(topicId)) { |
|
|
|
|
if (progressResult?.done?.includes(topicId)) { |
|
|
|
|
return 'done'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (progressResult?.learning.includes(topicId)) { |
|
|
|
|
if (progressResult?.learning?.includes(topicId)) { |
|
|
|
|
return 'learning'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (progressResult?.skipped?.includes(topicId)) { |
|
|
|
|
return 'skipped'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 'pending'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -46,6 +50,7 @@ export async function updateResourceProgress( |
|
|
|
|
const { response, error } = await httpPost<{ |
|
|
|
|
done: string[]; |
|
|
|
|
learning: string[]; |
|
|
|
|
skipped: string[]; |
|
|
|
|
}>(`${import.meta.env.PUBLIC_API_URL}/v1-update-resource-progress`, { |
|
|
|
|
topicId, |
|
|
|
|
resourceType, |
|
|
|
@ -61,20 +66,23 @@ export async function updateResourceProgress( |
|
|
|
|
resourceType, |
|
|
|
|
resourceId, |
|
|
|
|
response.done, |
|
|
|
|
response.learning |
|
|
|
|
response.learning, |
|
|
|
|
response.skipped, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
return response; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export async function getResourceProgress( |
|
|
|
|
resourceType: 'roadmap' | 'best-practice', |
|
|
|
|
resourceId: string |
|
|
|
|
): Promise<{ done: string[]; learning: string[] }> { |
|
|
|
|
): Promise<{ done: string[]; learning: string[], skipped: string[] }> { |
|
|
|
|
// No need to load progress if user is not logged in
|
|
|
|
|
if (!Cookies.get(TOKEN_COOKIE_NAME)) { |
|
|
|
|
return { |
|
|
|
|
done: [], |
|
|
|
|
learning: [], |
|
|
|
|
skipped: [], |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -101,31 +109,27 @@ async function loadFreshProgress( |
|
|
|
|
const { response, error } = await httpGet<{ |
|
|
|
|
done: string[]; |
|
|
|
|
learning: string[]; |
|
|
|
|
skipped: string[]; |
|
|
|
|
}>(`${import.meta.env.PUBLIC_API_URL}/v1-get-user-resource-progress`, { |
|
|
|
|
resourceType, |
|
|
|
|
resourceId, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if (error) { |
|
|
|
|
if (error || !response) { |
|
|
|
|
console.error(error); |
|
|
|
|
return { |
|
|
|
|
done: [], |
|
|
|
|
learning: [], |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!response?.done || !response?.learning) { |
|
|
|
|
return { |
|
|
|
|
done: [], |
|
|
|
|
learning: [], |
|
|
|
|
skipped: [], |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setResourceProgress( |
|
|
|
|
resourceType, |
|
|
|
|
resourceId, |
|
|
|
|
response.done, |
|
|
|
|
response.learning |
|
|
|
|
response?.done || [], |
|
|
|
|
response?.learning || [], |
|
|
|
|
response?.skipped || [], |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
return response; |
|
|
|
@ -135,13 +139,15 @@ export function setResourceProgress( |
|
|
|
|
resourceType: 'roadmap' | 'best-practice', |
|
|
|
|
resourceId: string, |
|
|
|
|
done: string[], |
|
|
|
|
learning: string[] |
|
|
|
|
learning: string[], |
|
|
|
|
skipped: string [], |
|
|
|
|
): void { |
|
|
|
|
localStorage.setItem( |
|
|
|
|
`${resourceType}-${resourceId}-progress`, |
|
|
|
|
JSON.stringify({ |
|
|
|
|
done, |
|
|
|
|
learning, |
|
|
|
|
skipped, |
|
|
|
|
timestamp: new Date().getTime(), |
|
|
|
|
}) |
|
|
|
|
); |
|
|
|
@ -152,6 +158,7 @@ export function renderTopicProgress( |
|
|
|
|
topicProgress: ResourceProgressType |
|
|
|
|
) { |
|
|
|
|
const isLearning = topicProgress === 'learning'; |
|
|
|
|
const isSkipped = topicProgress === 'skipped'; |
|
|
|
|
const isDone = topicProgress === 'done'; |
|
|
|
|
const matchingElements: Element[] = []; |
|
|
|
|
|
|
|
|
@ -185,13 +192,15 @@ export function renderTopicProgress( |
|
|
|
|
matchingElements.forEach((element) => { |
|
|
|
|
if (isDone) { |
|
|
|
|
element.classList.add('done'); |
|
|
|
|
element.classList.remove('learning'); |
|
|
|
|
element.classList.remove('learning', 'skipped'); |
|
|
|
|
} else if (isLearning) { |
|
|
|
|
element.classList.add('learning'); |
|
|
|
|
element.classList.remove('done'); |
|
|
|
|
element.classList.remove('done', 'skipped'); |
|
|
|
|
} else if (isSkipped) { |
|
|
|
|
element.classList.add('skipped'); |
|
|
|
|
element.classList.remove('done', 'learning'); |
|
|
|
|
} else { |
|
|
|
|
element.classList.remove('done'); |
|
|
|
|
element.classList.remove('learning'); |
|
|
|
|
element.classList.remove('done', 'skipped', 'learning'); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -200,7 +209,7 @@ export async function renderResourceProgress( |
|
|
|
|
resourceType: ResourceType, |
|
|
|
|
resourceId: string |
|
|
|
|
) { |
|
|
|
|
const { done = [], learning = [] } = |
|
|
|
|
const { done = [], learning = [], skipped = [] } = |
|
|
|
|
(await getResourceProgress(resourceType, resourceId)) || {}; |
|
|
|
|
|
|
|
|
|
done.forEach((topicId) => { |
|
|
|
@ -210,4 +219,8 @@ export async function renderResourceProgress( |
|
|
|
|
learning.forEach((topicId) => { |
|
|
|
|
renderTopicProgress(topicId, 'learning'); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
skipped.forEach((topicId) => { |
|
|
|
|
renderTopicProgress(topicId, 'skipped'); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|