get dashboard to a functional state
This commit is contained in:
parent
7df1faa0fa
commit
ea793dae09
|
@ -1,25 +1,25 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
const ProgressBar = ({ title }) => {
|
const ProgressBar = ({ text, green, yellow, blue }) => {
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="overflow-hidden h-4 text-xs flex rounded-full bg-gray-200">
|
<div className="overflow-hidden h-4 text-xs flex bg-gray-200">
|
||||||
<div
|
<div
|
||||||
style={{ width: '45%' }}
|
style={{ width: `${green}%` }}
|
||||||
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-green-500"
|
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-green-500"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
style={{ width: '10%' }}
|
style={{ width: `${yellow}%` }}
|
||||||
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-yellow-300"
|
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-yellow-300"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
style={{ width: '5%' }}
|
style={{ width: `${blue}%` }}
|
||||||
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-blue-500"
|
className="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right">
|
<div className="text-right">
|
||||||
<span className="text-sm font-semibold inline-block text-gray-800">
|
<span className="text-sm font-semibold inline-block text-gray-800">
|
||||||
107 total modules
|
{text}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -39,36 +39,47 @@ const FancyNumber = ({ number, text, textColor, bgColor }) => (
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function SectionProgress() {
|
export default function DashboardProgress({
|
||||||
|
completed,
|
||||||
|
inProgress,
|
||||||
|
skipped,
|
||||||
|
notStarted,
|
||||||
|
total,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="grid grid-cols-4 gap-2 mb-4">
|
<div className="grid grid-cols-4 gap-2 mb-4">
|
||||||
<FancyNumber
|
<FancyNumber
|
||||||
number="12"
|
number={completed}
|
||||||
text="Completed"
|
text="Completed"
|
||||||
textColor="text-green-800"
|
textColor="text-green-800"
|
||||||
bgColor="bg-green-100"
|
bgColor="bg-green-100"
|
||||||
/>
|
/>
|
||||||
<FancyNumber
|
<FancyNumber
|
||||||
number="3"
|
number={inProgress}
|
||||||
text="In Progress"
|
text="In Progress"
|
||||||
textColor="text-yellow-800"
|
textColor="text-yellow-800"
|
||||||
bgColor="bg-yellow-100"
|
bgColor="bg-yellow-100"
|
||||||
/>
|
/>
|
||||||
<FancyNumber
|
<FancyNumber
|
||||||
number="1"
|
number={skipped}
|
||||||
text="Skipped"
|
text="Skipped"
|
||||||
textColor="text-blue-800"
|
textColor="text-blue-800"
|
||||||
bgColor="bg-blue-50"
|
bgColor="bg-blue-50"
|
||||||
/>
|
/>
|
||||||
<FancyNumber
|
<FancyNumber
|
||||||
number="8"
|
number={notStarted}
|
||||||
text="Not Started"
|
text="Not Started"
|
||||||
textColor="text-gray-800"
|
textColor="text-gray-800"
|
||||||
bgColor="bg-gray-100"
|
bgColor="bg-gray-100"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ProgressBar title="Modules" />
|
<ProgressBar
|
||||||
|
green={(completed / total) * 100}
|
||||||
|
yellow={(inProgress / total) * 100}
|
||||||
|
blue={(skipped / total) * 100}
|
||||||
|
text={`${total} total`}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ import { graphql, Link, PageProps } from 'gatsby';
|
||||||
import Layout from '../components/layout';
|
import Layout from '../components/layout';
|
||||||
import SEO from '../components/seo';
|
import SEO from '../components/seo';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import SectionProgress from '../components/Dashboard/SectionProgress';
|
import DashboardProgress from '../components/Dashboard/DashboardProgress';
|
||||||
import SectionProgressBar from '../components/Dashboard/SectionProgressBar';
|
import SectionProgressBar from '../components/Dashboard/SectionProgressBar';
|
||||||
import UserDataContext from '../context/UserDataContext';
|
import UserDataContext from '../context/UserDataContext';
|
||||||
import WelcomeBackBanner from '../components/Dashboard/WelcomeBackBanner';
|
import WelcomeBackBanner from '../components/Dashboard/WelcomeBackBanner';
|
||||||
|
@ -15,6 +15,30 @@ import {
|
||||||
import DashboardNav from '../components/Dashboard/DashboardNav';
|
import DashboardNav from '../components/Dashboard/DashboardNav';
|
||||||
import ActiveItems, { ActiveItem } from '../components/Dashboard/ActiveItems';
|
import ActiveItems, { ActiveItem } from '../components/Dashboard/ActiveItems';
|
||||||
|
|
||||||
|
const getProgressInfo = (
|
||||||
|
keys: string[],
|
||||||
|
data: { [key: string]: string },
|
||||||
|
completedValues: string[],
|
||||||
|
inProgressValues: string[],
|
||||||
|
skippedValues: string[],
|
||||||
|
notStartedValues: string[]
|
||||||
|
) => {
|
||||||
|
let res = {
|
||||||
|
completed: 0,
|
||||||
|
inProgress: 0,
|
||||||
|
skipped: 0,
|
||||||
|
notStarted: 0,
|
||||||
|
};
|
||||||
|
for (let key of keys) {
|
||||||
|
if (!(key in data)) res.notStarted++;
|
||||||
|
else if (completedValues.includes(data[key])) res.completed++;
|
||||||
|
else if (inProgressValues.includes(data[key])) res.inProgress++;
|
||||||
|
else if (skippedValues.includes(data[key])) res.skipped++;
|
||||||
|
else if (notStartedValues.includes(data[key])) res.notStarted++;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
export default function DashboardPage(props: PageProps) {
|
export default function DashboardPage(props: PageProps) {
|
||||||
const { modules } = props.data as any;
|
const { modules } = props.data as any;
|
||||||
const moduleIDToName = modules.edges.reduce((acc, cur) => {
|
const moduleIDToName = modules.edges.reduce((acc, cur) => {
|
||||||
|
@ -28,6 +52,7 @@ export default function DashboardPage(props: PageProps) {
|
||||||
url: `${moduleIDToURLMap[cur.node.frontmatter.id]}/#problem-${
|
url: `${moduleIDToURLMap[cur.node.frontmatter.id]}/#problem-${
|
||||||
problem.uniqueID
|
problem.uniqueID
|
||||||
}`,
|
}`,
|
||||||
|
starred: problem.starred,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return acc;
|
return acc;
|
||||||
|
@ -68,6 +93,36 @@ export default function DashboardPage(props: PageProps) {
|
||||||
}));
|
}));
|
||||||
}, [userProgressOnProblems]);
|
}, [userProgressOnProblems]);
|
||||||
|
|
||||||
|
let allModulesProgressInfo = getProgressInfo(
|
||||||
|
Object.keys(moduleIDToName),
|
||||||
|
userProgressOnModules,
|
||||||
|
['Complete'],
|
||||||
|
['Reading', 'Practicing'],
|
||||||
|
['Skipped'],
|
||||||
|
['Not Started']
|
||||||
|
);
|
||||||
|
|
||||||
|
const allProblemIDs = Object.keys(problemIDMap);
|
||||||
|
// const allStarredProblemIDs = allProblemIDs.filter(
|
||||||
|
// x => problemIDMap[x].starred
|
||||||
|
// );
|
||||||
|
const allProblemsProgressInfo = getProgressInfo(
|
||||||
|
allProblemIDs,
|
||||||
|
userProgressOnProblems,
|
||||||
|
['Solved'],
|
||||||
|
['Solving'],
|
||||||
|
['Skipped'],
|
||||||
|
['Not Attempted']
|
||||||
|
);
|
||||||
|
// const allStarredProblemsProgressInfo = getProgressInfo(
|
||||||
|
// allStarredProblemIDs,
|
||||||
|
// userProgressOnProblems,
|
||||||
|
// ['Solved'],
|
||||||
|
// ['Solving'],
|
||||||
|
// ['Skipped'],
|
||||||
|
// ['Not Attempted']
|
||||||
|
// );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<SEO title="Dashboard" />
|
<SEO title="Dashboard" />
|
||||||
|
@ -96,37 +151,37 @@ export default function DashboardPage(props: PageProps) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<header>
|
{/*<header>*/}
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
{/* <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">*/}
|
||||||
<h1 className="text-3xl font-bold leading-tight text-gray-900">
|
{/* <h1 className="text-3xl font-bold leading-tight text-gray-900">*/}
|
||||||
Announcements
|
{/* Announcements*/}
|
||||||
</h1>
|
{/* </h1>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</header>
|
{/*</header>*/}
|
||||||
<div className="max-w-7xl mx-auto mb-8">
|
{/*<div className="max-w-7xl mx-auto mb-8">*/}
|
||||||
<div className="flex overflow-x-auto sm:px-6 lg:px-8 py-4 lg:grid lg:grid-cols-2 lg:gap-8">
|
{/* <div className="flex overflow-x-auto sm:px-6 lg:px-8 py-4 lg:grid lg:grid-cols-2 lg:gap-8">*/}
|
||||||
<div className="bg-white shadow hover:shadow-lg transition duration-150 ease-in-out sm:rounded-lg">
|
{/* <div className="bg-white shadow hover:shadow-lg transition duration-150 ease-in-out sm:rounded-lg">*/}
|
||||||
<div className="px-4 py-5 sm:p-6 cursor-pointer">
|
{/* <div className="px-4 py-5 sm:p-6 cursor-pointer">*/}
|
||||||
<p className="text-sm leading-5 text-gray-500">
|
{/* <p className="text-sm leading-5 text-gray-500">*/}
|
||||||
<time dateTime="2020-07-18">July 18, 2020</time>
|
{/* <time dateTime="2020-07-18">July 18, 2020</time>*/}
|
||||||
</p>
|
{/* </p>*/}
|
||||||
<h3 className="mt-2 text-xl leading-7 font-semibold text-gray-900">
|
{/* <h3 className="mt-2 text-xl leading-7 font-semibold text-gray-900">*/}
|
||||||
Looking for Contributors!
|
{/* Looking for Contributors!*/}
|
||||||
</h3>
|
{/* </h3>*/}
|
||||||
<p className="mt-3 text-base leading-6 text-gray-500">
|
{/* <p className="mt-3 text-base leading-6 text-gray-500">*/}
|
||||||
Welcome to the USACO Guide! We're still in pre-release mode,
|
{/* Welcome to the USACO Guide! We're still in pre-release mode,*/}
|
||||||
so things may be a bit rough around the edges. Learn more
|
{/* so things may be a bit rough around the edges. Learn more*/}
|
||||||
about what this means, and how you can help contribute!
|
{/* about what this means, and how you can help contribute!*/}
|
||||||
</p>
|
{/* </p>*/}
|
||||||
<div className="mt-3">
|
{/* <div className="mt-3">*/}
|
||||||
<span className="text-base leading-6 font-semibold text-indigo-600 hover:text-indigo-500 transition ease-in-out duration-150">
|
{/* <span className="text-base leading-6 font-semibold text-indigo-600 hover:text-indigo-500 transition ease-in-out duration-150">*/}
|
||||||
Continue Reading
|
{/* Continue Reading*/}
|
||||||
</span>
|
{/* </span>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</div>
|
{/*</div>*/}
|
||||||
<header>
|
<header>
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h1 className="text-3xl font-bold leading-tight text-gray-900">
|
<h1 className="text-3xl font-bold leading-tight text-gray-900">
|
||||||
|
@ -136,39 +191,48 @@ export default function DashboardPage(props: PageProps) {
|
||||||
</header>
|
</header>
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
<div className="sm:px-6 lg:px-8 py-4 lg:grid lg:grid-cols-2 lg:gap-8 space-y-8 lg:space-y-0">
|
<div className="sm:px-6 lg:px-8 py-4 lg:grid lg:grid-cols-2 lg:gap-8 space-y-8 lg:space-y-0">
|
||||||
<div className="space-y-8 order-2">
|
<div className="space-y-8">
|
||||||
<div className="bg-white shadow sm:rounded-lg">
|
<div className="bg-white shadow sm:rounded-lg">
|
||||||
<div className="px-4 py-5 sm:p-6">
|
<div className="px-4 py-5 sm:p-6">
|
||||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||||
All Modules
|
All Modules
|
||||||
</h3>
|
</h3>
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<SectionProgress />
|
<DashboardProgress
|
||||||
</div>
|
{...allModulesProgressInfo}
|
||||||
</div>
|
total={Object.keys(moduleIDToName).length}
|
||||||
</div>
|
/>
|
||||||
<div className="bg-white shadow sm:rounded-lg">
|
|
||||||
<div className="px-4 py-5 sm:p-6">
|
|
||||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
|
||||||
All Starred Problems
|
|
||||||
</h3>
|
|
||||||
<div className="mt-6">
|
|
||||||
<SectionProgress />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/*<div className="bg-white shadow sm:rounded-lg">*/}
|
||||||
|
{/* <div className="px-4 py-5 sm:p-6">*/}
|
||||||
|
{/* <h3 className="text-lg leading-6 font-medium text-gray-900">*/}
|
||||||
|
{/* All Starred Problems*/}
|
||||||
|
{/* </h3>*/}
|
||||||
|
{/* <div className="mt-6">*/}
|
||||||
|
{/* <DashboardProgress*/}
|
||||||
|
{/* {...allStarredProblemsProgressInfo}*/}
|
||||||
|
{/* total={Object.keys(allStarredProblemIDs).length}*/}
|
||||||
|
{/* />*/}
|
||||||
|
{/* </div>*/}
|
||||||
|
{/* </div>*/}
|
||||||
|
{/*</div>*/}
|
||||||
|
</div>
|
||||||
|
<div className="space-y-8">
|
||||||
<div className="bg-white shadow sm:rounded-lg order-6">
|
<div className="bg-white shadow sm:rounded-lg order-6">
|
||||||
<div className="px-4 py-5 sm:p-6">
|
<div className="px-4 py-5 sm:p-6">
|
||||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||||
All Problems
|
All Problems
|
||||||
</h3>
|
</h3>
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<SectionProgress />
|
<DashboardProgress
|
||||||
|
{...allProblemsProgressInfo}
|
||||||
|
total={Object.keys(allProblemIDs).length}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div className="space-y-8 order-1">
|
|
||||||
{/*<div className="bg-white shadow sm:rounded-lg overflow-hidden row-span-2 flex flex-col">*/}
|
{/*<div className="bg-white shadow sm:rounded-lg overflow-hidden row-span-2 flex flex-col">*/}
|
||||||
{/* <div className="px-4 pt-5 sm:px-6 sm:pt-6 pb-4">*/}
|
{/* <div className="px-4 pt-5 sm:px-6 sm:pt-6 pb-4">*/}
|
||||||
{/* <h3 className="text-lg leading-6 font-medium text-gray-900">*/}
|
{/* <h3 className="text-lg leading-6 font-medium text-gray-900">*/}
|
||||||
|
@ -187,24 +251,24 @@ export default function DashboardPage(props: PageProps) {
|
||||||
{/* alt="Cow"*/}
|
{/* alt="Cow"*/}
|
||||||
{/* />*/}
|
{/* />*/}
|
||||||
{/*</div>*/}
|
{/*</div>*/}
|
||||||
<div className="bg-white shadow sm:rounded-lg">
|
{/*<div className="bg-white shadow sm:rounded-lg">*/}
|
||||||
<div className="px-4 py-5 sm:p-6">
|
{/* <div className="px-4 py-5 sm:p-6">*/}
|
||||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
{/* <h3 className="text-lg leading-6 font-medium text-gray-900">*/}
|
||||||
Section Breakdown
|
{/* Section Breakdown*/}
|
||||||
</h3>
|
{/* </h3>*/}
|
||||||
<div className="mt-2 max-w-xl text-sm leading-5 text-gray-500">
|
{/* <div className="mt-2 max-w-xl text-sm leading-5 text-gray-500">*/}
|
||||||
<p>Below is your progress on modules for each section.</p>
|
{/* <p>Below is your progress on modules for each section.</p>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
<div className="mt-4">
|
{/* <div className="mt-4">*/}
|
||||||
<SectionProgressBar title="Intro" />
|
{/* <SectionProgressBar title="Intro" />*/}
|
||||||
<SectionProgressBar title="Bronze" />
|
{/* <SectionProgressBar title="Bronze" />*/}
|
||||||
<SectionProgressBar title="Silver" />
|
{/* <SectionProgressBar title="Silver" />*/}
|
||||||
<SectionProgressBar title="Gold" />
|
{/* <SectionProgressBar title="Gold" />*/}
|
||||||
<SectionProgressBar title="Plat" />
|
{/* <SectionProgressBar title="Plat" />*/}
|
||||||
<SectionProgressBar title="Advanced" />
|
{/* <SectionProgressBar title="Advanced" />*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</div>
|
{/* </div>*/}
|
||||||
</div>
|
{/*</div>*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -227,6 +291,7 @@ export const pageQuery = graphql`
|
||||||
uniqueID
|
uniqueID
|
||||||
source
|
source
|
||||||
name
|
name
|
||||||
|
starred
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ export default function IndexPage(props: PageProps) {
|
||||||
<div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
|
<div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
|
||||||
<div className="rounded-md shadow">
|
<div className="rounded-md shadow">
|
||||||
<Link
|
<Link
|
||||||
to="/intro"
|
to="/dashboard"
|
||||||
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
|
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
|
||||||
>
|
>
|
||||||
View Guide
|
View Guide
|
||||||
|
@ -486,7 +486,7 @@ export default function IndexPage(props: PageProps) {
|
||||||
<div className="mt-8 flex justify-center">
|
<div className="mt-8 flex justify-center">
|
||||||
<div className="rounded-md shadow">
|
<div className="rounded-md shadow">
|
||||||
<Link
|
<Link
|
||||||
to="/intro"
|
to="/dashboard"
|
||||||
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
|
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
|
||||||
>
|
>
|
||||||
View Guide
|
View Guide
|
||||||
|
|
Reference in a new issue