Add progress loading on homepage roadmaps

pull/4047/head
Kamran Ahmed 1 year ago
parent 502b8e20d5
commit 43f351a943
  1. 4
      src/components/FeaturedItems/FeaturedItem.astro
  2. 20
      src/components/Navigation/Navigation.astro
  3. 2
      src/layouts/BaseLayout.astro
  4. 57
      src/lib/home-progress.ts
  5. 2
      src/pages/404.astro
  6. 27
      src/pages/index.astro

@ -13,14 +13,14 @@ const { isUpcoming = false, isNew = false, text, url } = Astro.props;
<a
class:list={[
'group border border-slate-800 bg-slate-900 p-2.5 sm:p-3.5 block no-underline rounded-lg relative text-slate-400 font-regular text-md hover:border-slate-600 hover:text-slate-100',
'group border border-slate-800 bg-slate-900 p-2.5 sm:p-3.5 block no-underline rounded-lg relative text-slate-400 font-regular text-md hover:border-slate-600 hover:text-slate-100 overflow-hidden',
{
'opacity-50': isUpcoming,
},
]}
href={url}
>
<span class='text-slate-400'>
<span class='text-slate-400 relative z-20'>
{text}
</span>

@ -5,7 +5,11 @@ import AccountDropdown from './AccountDropdown.astro';
<div class='bg-slate-900 py-5 text-white sm:py-8'>
<nav class='container flex items-center justify-between'>
<a class='flex items-center text-lg font-medium text-white' href='/' aria-label="roadmap.sh">
<a
class='flex items-center text-lg font-medium text-white'
href='/'
aria-label='roadmap.sh'
>
<Icon icon='logo' />
</a>
@ -26,9 +30,12 @@ import AccountDropdown from './AccountDropdown.astro';
<a href='/videos' class='text-gray-400 hover:text-white'>Videos</a>
</li>
<li>
<kbd data-command-menu class="hidden sm:flex items-center text-gray-400 border border-gray-800 rounded-md px-2.5 py-1 text-sm hover:bg-gray-800 hover:cursor-pointer">
<Icon icon='search' class='h-3 w-3 mr-2' />
<kbd class='font-sans mr-1'>⌘</kbd><kbd class='font-sans'>K</kbd>
<kbd
data-command-menu
class='hidden items-center rounded-md border border-gray-800 px-2.5 py-1 text-sm text-gray-400 hover:cursor-pointer hover:bg-gray-800 sm:flex'
>
<Icon icon='search' class='mr-2 h-3 w-3' />
<kbd class='mr-1 font-sans'>⌘</kbd><kbd class='font-sans'>K</kbd>
</kbd>
</li>
</ul>
@ -97,10 +104,7 @@ import AccountDropdown from './AccountDropdown.astro';
<!-- Links for logged in users -->
<li data-auth-required class='hidden'>
<a
href='/account'
class='text-xl hover:text-blue-300 md:text-lg'
>
<a href='/account' class='text-xl hover:text-blue-300 md:text-lg'>
Account
</a>
</li>

@ -149,8 +149,8 @@ const gaPageIdentifier = Astro.url.pathname
</slot>
<Authenticator />
<PageProgress initialMessage={initialLoadingMessage} client:idle />
<CommandMenu client:idle />
<PageProgress initialMessage={initialLoadingMessage} client:idle />
<PageSponsor
gaPageIdentifier={briefTitle || gaPageIdentifier}
client:load

@ -0,0 +1,57 @@
import { httpGet } from './http';
import { isLoggedIn } from './jwt';
type UserProgressResponse = {
resourceId: string;
resourceType: 'roadmap' | 'best-practice';
done: number;
learning: number;
skipped: number;
total: number;
updatedAt: Date;
}[];
async function renderProgress() {
if (!isLoggedIn()) {
return;
}
const { response: progressList, error } = await httpGet<UserProgressResponse>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-user-all-progress`
);
if (error || !progressList) {
return;
}
progressList.forEach((progress) => {
const href =
progress.resourceType === 'best-practice'
? `/best-practices/${progress.resourceId}`
: `/${progress.resourceId}`;
const element = document.querySelector(`a[href="${href}"]`);
if (!element) {
return;
}
const totalDone = progress.done + progress.skipped;
const percentageDone = (totalDone / progress.total) * 100;
const progressBar = document.createElement('div');
progressBar.style.backgroundColor = 'rgb(23 42 58)';
progressBar.style.position = 'absolute';
progressBar.style.width = `${percentageDone}%`;
progressBar.style.height = '100%';
progressBar.style.bottom = '0';
progressBar.style.left = '0';
progressBar.style.top = '0';
progressBar.style.zIndex = '1';
element.appendChild(progressBar);
});
}
// on DOM load
window.addEventListener('DOMContentLoaded', () => {
window.setTimeout(renderProgress, 0);
});

@ -8,7 +8,7 @@ const legacyRoadmapUrls = [...roadmapIds.map((id) => `/${id}/`), '/roadmaps/'];
---
<BaseLayout title='Page not found' permalink={'/404'} noIndex={true}>
<!-- Legacy roadmp pages handling -->
<!-- Legacy roadmap pages handling -->
<script slot='after-header' define:vars={{ legacyRoadmapUrls }}>
// If it's a roadmap page and it ends with a slash
// redirect to the same page without the slash

@ -23,20 +23,24 @@ const videos = await getAllVideos();
>
<div class='bg-gradient-to-b from-slate-900 to-black'>
<div class='border-b border-b-[#1e293c]'>
<div class='container text-left sm:text-center py-6 pb-14 sm:py-20 px-6 sm:px-0'>
<div
class='container px-6 py-6 pb-14 text-left sm:px-0 sm:py-20 sm:text-center'
>
<h1
class='text-2xl sm:text-5xl mb-2 sm:mb-4 font-bold bg-gradient-to-b from-amber-50 to-purple-500 text-transparent bg-clip-text'
class='mb-2 bg-gradient-to-b from-amber-50 to-purple-500 bg-clip-text text-2xl font-bold text-transparent sm:mb-4 sm:text-5xl'
>
Developer Roadmaps
</h1>
<p class='hidden sm:block text-gray-400 text-lg px-4'>
<span class='font-medium text-gray-400'>roadmap.sh</span> is a community effort to create roadmaps, guides and
other educational content to help guide developers in picking up the path and guide their learnings.
<p class='hidden px-4 text-lg text-gray-400 sm:block'>
<span class='font-medium text-gray-400'>roadmap.sh</span> is a community
effort to create roadmaps, guides and other educational content to help
guide developers in picking up the path and guide their learnings.
</p>
<p class='block sm:hidden text-gray-400 text-md px-0'>
Community created roadmaps, guides and articles to help developers grow in their career.
<p class='text-md block px-0 text-gray-400 sm:hidden'>
Community created roadmaps, guides and articles to help developers
grow in their career.
</p>
</div>
</div>
@ -54,7 +58,10 @@ const videos = await getAllVideos();
<FeaturedItems
heading='Skill based Roadmaps'
featuredItems={skillRoadmaps.map((roadmapItem) => ({
text: roadmapItem.frontmatter.briefTitle === 'Go' ? 'Go Roadmap' : roadmapItem.frontmatter.briefTitle,
text:
roadmapItem.frontmatter.briefTitle === 'Go'
? 'Go Roadmap'
: roadmapItem.frontmatter.briefTitle,
url: `/${roadmapItem.id}`,
isNew: roadmapItem.frontmatter.isNew,
isUpcoming: roadmapItem.frontmatter.isUpcoming,
@ -71,9 +78,11 @@ const videos = await getAllVideos();
}))}
/>
<div class='grid grid-cols-1 gap-7 sm:gap-16 bg-gray-50 py-7 sm:py-16'>
<div class='grid grid-cols-1 gap-7 bg-gray-50 py-7 sm:gap-16 sm:py-16'>
<FeaturedGuides heading='Guides' guides={guides.slice(0, 7)} />
<FeaturedVideos heading='Videos' videos={videos.slice(0, 7)} />
</div>
</div>
<script src='../lib/home-progress.ts'></script>
</BaseLayout>

Loading…
Cancel
Save