get dashboard to a functional state

This commit is contained in:
Nathan Wang 2020-07-19 13:07:21 -07:00
parent 7df1faa0fa
commit ea793dae09
3 changed files with 155 additions and 79 deletions

View file

@ -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>
); );
} }

View file

@ -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
} }
} }
} }

View file

@ -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