more work on dashboard

This commit is contained in:
Nathan Wang 2020-07-18 01:27:36 -07:00
parent 481949f611
commit d37c2d7a49
10 changed files with 479 additions and 565 deletions

View file

@ -1,357 +0,0 @@
import * as React from 'react';
import { PageProps } from 'gatsby';
import Layout from '../components/layout';
import SEO from '../components/seo';
import Sidebar, { SidebarLogo } from '../components/Sidebar/Sidebar';
import { useState } from 'react';
// @ts-ignore
import logo from '../assets/logo.svg';
export default function SyllabusPage(props: PageProps) {
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
return (
<Layout>
<SEO title="Syllabus" />
<div className="h-screen flex overflow-hidden bg-gray-100">
<Sidebar
isMobileNavOpen={isMobileNavOpen}
onMobileNavStateChange={setIsMobileNavOpen}
mobileSidebarContent={
<>
<div className="flex-shrink-0 flex items-center px-4">
<img
className="h-8 w-auto"
src="https://tailwindui.com/img/logos/workflow-logo-on-brand.svg"
alt="Workflow"
/>
</div>
<div className="mt-5 flex-1 h-0 overflow-y-auto">
<nav className="px-2">
<a
href="#"
className="group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-white bg-indigo-900 focus:outline-none focus:bg-indigo-700 transition ease-in-out duration-150"
>
<svg
className="mr-4 h-6 w-6 text-indigo-400 group-hover:text-indigo-300 group-focus:text-indigo-300 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
Dashboard
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-indigo-300 hover:text-white hover:bg-indigo-700 focus:outline-none focus:text-white focus:bg-indigo-700 transition ease-in-out duration-150"
>
<svg
className="mr-4 h-6 w-6 text-indigo-400 group-hover:text-indigo-300 group-focus:text-indigo-300 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
Team
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-indigo-300 hover:text-white hover:bg-indigo-700 focus:outline-none focus:text-white focus:bg-indigo-700 transition ease-in-out duration-150"
>
<svg
className="mr-4 h-6 w-6 text-indigo-400 group-hover:text-indigo-300 group-focus:text-indigo-300 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
/>
</svg>
Projects
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-indigo-300 hover:text-white hover:bg-indigo-700 focus:outline-none focus:text-white focus:bg-indigo-700 transition ease-in-out duration-150"
>
<svg
className="mr-4 h-6 w-6 text-indigo-400 group-hover:text-indigo-300 group-focus:text-indigo-300 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
Calendar
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-indigo-300 hover:text-white hover:bg-indigo-700 focus:outline-none focus:text-white focus:bg-indigo-700 transition ease-in-out duration-150"
>
<svg
className="mr-4 h-6 w-6 text-indigo-400 group-hover:text-indigo-300 group-focus:text-indigo-300 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
/>
</svg>
Documents
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-indigo-300 hover:text-white hover:bg-indigo-700 focus:outline-none focus:text-white focus:bg-indigo-700 transition ease-in-out duration-150"
>
<svg
className="mr-4 h-6 w-6 text-indigo-400 group-hover:text-indigo-300 group-focus:text-indigo-300 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
</svg>
Reports
</a>
</nav>
</div>
</>
}
desktopSidebarContent={
<div className="flex w-64 flex-col border-r border-gray-200 pb-4 bg-white">
<div className="flex items-center flex-shrink-0 px-4 pt-3 pb-1">
<img className="h-12 w-auto" src={logo} alt="Workflow" />
</div>
<div className="mt-2 h-0 flex-1 flex flex-col overflow-y-auto">
{/* Sidebar component, swap this element with another sidebar if you like */}
<nav className="flex-1 px-2 bg-white">
<a
href="#"
className="group flex items-center px-2 py-2 text-sm leading-5 font-medium text-gray-900 rounded-md bg-gray-100 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:bg-gray-200 transition ease-in-out duration-150"
>
Intro
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-sm leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
>
<svg
className="mr-3 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
/>
</svg>
Team
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-sm leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
>
<svg
className="mr-3 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
/>
</svg>
Projects
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-sm leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
>
<svg
className="mr-3 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
Calendar
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-sm leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
>
<svg
className="mr-3 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
/>
</svg>
Documents
</a>
<a
href="#"
className="mt-1 group flex items-center px-2 py-2 text-sm leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
>
<svg
className="mr-3 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
</svg>
Reports
</a>
</nav>
</div>
</div>
}
>
<div>
<div className="relative z-10 flex-shrink-0 flex h-16 bg-white shadow">
<button
className="px-4 border-r border-gray-200 text-gray-500 focus:outline-none focus:bg-gray-100 focus:text-gray-600 md:hidden"
aria-label="Open sidebar"
>
<svg
className="h-6 w-6"
stroke="currentColor"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h7"
/>
</svg>
</button>
<div className="flex-1 px-6 flex justify-between">
<div className="flex-1 flex">
<form className="w-full flex md:ml-0" action="#" method="GET">
<label htmlFor="search_field" className="sr-only">
Search
</label>
<div className="relative w-full text-gray-400 focus-within:text-gray-600">
<div className="absolute inset-y-0 left-0 flex items-center pointer-events-none">
<svg
className="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
/>
</svg>
</div>
<input
id="search_field"
className="block w-full h-full pl-8 pr-3 py-2 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400"
placeholder="Search"
type="search"
/>
</div>
</form>
</div>
<div className="ml-4 flex items-center md:ml-6">
<button
className="p-1 text-gray-400 rounded-full hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:shadow-outline focus:text-gray-500"
aria-label="Notifications"
>
<svg
className="h-6 w-6"
stroke="currentColor"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
/>
</svg>
</button>
</div>
</div>
</div>
<main
className="flex-1 relative z-0 overflow-y-auto focus:outline-none"
tabIndex={0}
>
<div className="pt-2 pb-6 md:py-6">
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
<h1 className="text-2xl font-semibold text-gray-900">
Dashboard
</h1>
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
{/* Replace with your content */}
<div className="py-4">
<div className="border-4 border-dashed border-gray-200 rounded-lg h-96" />
</div>
{/* /End replace */}
</div>
</div>
</main>
</div>
</Sidebar>
</div>
</Layout>
);
}

View file

@ -15,7 +15,7 @@ type SlideoverProps = {
export default function SlideoverForm(props: SlideoverProps) {
return (
<Transition show={props.isOpen} timeout={700}>
<div className="fixed inset-0 overflow-hidden">
<div className="fixed inset-0 overflow-hidden z-10">
<div className="absolute inset-0 overflow-hidden">
<Transition
enter="ease-in-out duration-500"

View file

@ -17,12 +17,16 @@ import MarkCompleteButton from './MarkCompleteButton';
import ModuleConfetti from './ModuleConfetti';
import TextTooltip from '../Tooltip/TextTooltip';
import UserDataContext, { UserLang } from '../../context/UserDataContext';
import { NavLinkGroup, SidebarNav } from './SidebarNav/SidebarNav';
import {
NavLinkGroup,
ModuleSidebarNav,
} from './ModuleSidebarNav/ModuleSidebarNav';
import { graphqlToModuleLinks } from '../../utils';
import ModuleLayoutContext from '../../context/ModuleLayoutContext';
import TableOfContentsSidebar from './TableOfContents/TableOfContentsSidebar';
import TableOfContentsBlock from './TableOfContents/TableOfContentsBlock';
import Sidebar, { SidebarLogo } from '../Sidebar/Sidebar';
import SidebarBottomButtons from '../Sidebar/SidebarBottomButtons';
const Frequency = ({ frequency }: { frequency: ModuleFrequency }) => {
const textColors = [
@ -114,64 +118,6 @@ const Breadcrumbs = () => {
);
};
const SidebarBottomButtons = ({ onContactUs }) => {
const languages = {
showAll: 'All',
cpp: 'C++',
java: 'Java',
py: 'Python',
};
const nextLang: { [key: string]: UserLang } = {
showAll: 'cpp',
cpp: 'java',
java: 'py',
py: 'cpp',
};
const userSettings = useContext(UserDataContext);
return (
<>
<div className="flex-shrink-0 border-t border-gray-200 flex">
<button
className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
onClick={() => userSettings.setLang(nextLang[userSettings.lang])}
>
<svg
className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
Language: {languages[userSettings.lang]}
</button>
</div>
<div className="flex-shrink-0 border-t border-gray-200 flex">
<button
className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
onClick={onContactUs}
>
<svg
className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
</svg>
Contact Us
</button>
</div>
</>
);
};
const NavBar = ({ alignNavButtonsRight = true }) => {
const moduleLayoutInfo = useContext(ModuleLayoutContext);
const { module, moduleLinks } = moduleLayoutInfo;
@ -278,7 +224,6 @@ export default function ModuleLayout({
const { userProgressOnModules, setModuleProgress, lang } = useContext(
UserDataContext
);
const [isContactUsActive, setIsContactUsActive] = useState(false);
const [isConfettiActive, setIsConfettiActive] = useState(false);
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
const moduleProgress =
@ -326,64 +271,20 @@ export default function ModuleLayout({
onDone={() => setIsConfettiActive(false)}
/>
<Sidebar
activeModule={module}
isMobileNavOpen={isMobileNavOpen}
onMobileNavStateChange={setIsMobileNavOpen}
desktopSidebarContent={<ModuleSidebarNav />}
mobileSidebarContent={
<div className="relative flex-1 flex flex-col max-w-xs w-full bg-white">
<div className="absolute top-0 right-0 -mr-14 p-1">
<button
className="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600"
aria-label="Close sidebar"
onClick={() => setIsMobileNavOpen(false)}
>
<svg
className="h-6 w-6 text-white"
stroke="currentColor"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
<>
<SidebarLogo />
<div className="mt-4 px-6">
<Breadcrumbs />
</div>
<div className="flex-1 h-0 pt-5 overflow-y-auto">
<SidebarLogo />
<div className="mt-4 px-6">
<Breadcrumbs />
</div>
<nav className="mt-6">
<SidebarNav />
</nav>
</div>
<SidebarBottomButtons
onContactUs={() => {
setIsMobileNavOpen(false);
setIsContactUsActive(true);
}}
/>
</div>
}
desktopSidebarContent={
<div
className="flex flex-col border-r border-gray-200 bg-white"
style={{ width: '20rem' }}
>
<div className="h-0 flex-1 flex flex-col pt-5 overflow-y-auto">
<SidebarLogo />
{/* Sidebar component, swap this element with another sidebar if you like */}
<nav className="mt-2 flex-1 bg-white">
<SidebarNav />
</nav>
</div>
<SidebarBottomButtons
onContactUs={() => setIsContactUsActive(true)}
/>
</div>
<nav className="mt-6">
<ModuleSidebarNav />
</nav>
</>
}
>
<div className="lg:hidden pl-1 pt-1 sm:pl-3 sm:pt-3 flex items-center">
@ -510,11 +411,6 @@ export default function ModuleLayout({
</div>
</main>
</Sidebar>
<ContactUsSlideover
isOpen={isContactUsActive}
onClose={() => setIsContactUsActive(false)}
activeModule={module}
/>
</ModuleLayoutContext.Provider>
);
}

View file

@ -1,81 +1,11 @@
import * as React from 'react';
import { Link } from 'gatsby';
import { ModuleLinkInfo } from '../../../models/module';
import styled from 'styled-components';
import tw from 'twin.macro';
import { useContext } from 'react';
import ModuleLayoutContext from '../../../context/ModuleLayoutContext';
import UserDataContext from '../../../context/UserDataContext';
const LinkWithProgress = styled.span`
${tw`block relative`}
&::after {
content: '';
left: 24px;
top: 18px;
height: 8px;
width: 8px;
position: absolute;
transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1) 0s;
}
&::after {
border-radius: 100%;
${props => props.dotColorStyle};
}
&::before {
content: '';
position: absolute;
width: 2px;
display: block;
left: 27px;
top: 0;
bottom: 0;
${props => props.lineColorStyle};
}
&:first-of-type::before {
top: 22px;
}
&:last-of-type::before {
bottom: calc(100% - 22px);
}
`;
const StyledLink = styled.span`
${tw`focus:outline-none transition ease-in-out duration-150 hover:text-blue-700 hover:bg-blue-50 focus:bg-blue-100 flex items-center pl-12 pr-4 py-3 text-sm leading-5`}
${({ isActive, activeTextStyle }) =>
isActive ? activeTextStyle : tw`text-gray-600`}
&::before {
content: '';
left: 24px;
top: 18px;
height: 8px;
width: 8px;
position: absolute;
transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1) 0s;
}
&::before {
transform: ${({ isActive }) => (isActive ? 'scale(1)' : 'scale(0.1)')};
border-radius: 100%;
z-index: 1;
${({ dotColorStyle }) => dotColorStyle}
}
&:hover {
&::before {
transform: scale(1);
${tw`bg-blue-600`}
}
}
`;
import SidebarLink from '../../Sidebar/SidebarLink';
const ItemLink = ({ link }: { link: ModuleLinkInfo }) => {
const { module } = useContext(ModuleLayoutContext);
@ -119,21 +49,16 @@ const ItemLink = ({ link }: { link: ModuleLinkInfo }) => {
}
return (
<LinkWithProgress
lineColorStyle={lineColorStyle}
<SidebarLink
isActive={isActive}
textStyle={isActive ? activeTextStyle : tw`text-gray-600`}
dotColorStyle={dotColorStyle}
lineColorStyle={lineColorStyle}
linkRef={itemRef}
url={link.url}
>
<Link to={link.url}>
<StyledLink
isActive={isActive}
ref={itemRef}
dotColorStyle={dotColorStyle === tw`bg-gray-200`}
activeTextStyle={activeTextStyle}
>
{link.title}
</StyledLink>
</Link>
</LinkWithProgress>
{link.title}
</SidebarLink>
);
};

View file

@ -11,7 +11,7 @@ export interface NavLinkGroup {
children: ModuleLinkInfo[];
}
export const SidebarNav = () => {
export const ModuleSidebarNav = () => {
const { module, moduleLinks } = useContext(ModuleLayoutContext);
const links: NavLinkGroup[] = React.useMemo(() => {

View file

@ -1,10 +1,13 @@
import * as React from 'react';
import Transition from '../Transition';
import { Link } from 'gatsby';
import { SidebarNav } from '../ModuleLayout/SidebarNav/SidebarNav';
import { ModuleSidebarNav } from '../ModuleLayout/ModuleSidebarNav/ModuleSidebarNav';
// @ts-ignore
import logo from '../../assets/logo.svg';
import { createContext, useState } from 'react';
import SidebarBottomButtons from './SidebarBottomButtons';
import ContactUsSlideover from '../ContactUsSlideover/ContactUsSlideover';
import ModuleLayoutContext from '../../context/ModuleLayoutContext';
export const SidebarLogo = () => {
return (
@ -19,10 +22,19 @@ export default function Sidebar({
onMobileNavStateChange,
mobileSidebarContent,
desktopSidebarContent,
activeModule = null,
children,
}) {
const [isContactUsActive, setIsContactUsActive] = useState(false);
return (
<>
<ContactUsSlideover
isOpen={isContactUsActive}
onClose={() => setIsContactUsActive(false)}
activeModule={activeModule}
/>
<Transition show={isMobileNavOpen} timeout={300}>
<div className="lg:hidden">
<div className="fixed inset-0 flex z-40">
@ -50,7 +62,32 @@ export default function Sidebar({
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
{mobileSidebarContent}
<div className="relative flex-1 flex flex-col max-w-xs w-full bg-white">
<div className="absolute top-0 right-0 -mr-14 p-1">
<button
className="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600"
aria-label="Close sidebar"
onClick={() => onMobileNavStateChange(false)}
>
<svg
className="h-6 w-6 text-white"
stroke="currentColor"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div className="flex-1 h-0 pt-5 overflow-y-auto">
{mobileSidebarContent}
</div>
</div>
</Transition>
<div className="flex-shrink-0 w-14">
{/* Force sidebar to shrink to fit close icon */}
@ -60,7 +97,18 @@ export default function Sidebar({
</Transition>
{/* Static sidebar for desktop */}
<div className="hidden lg:flex lg:flex-shrink-0">
{desktopSidebarContent}
<div
className="flex flex-col border-r border-gray-200 bg-white"
style={{ width: '20rem' }}
>
<div className="flex flex-col py-2 overflow-y-auto">
<SidebarLogo />
</div>
<nav className="flex-1">{desktopSidebarContent}</nav>
<SidebarBottomButtons
onContactUs={() => setIsContactUsActive(true)}
/>
</div>
</div>
<div className="flex flex-col w-0 flex-1 overflow-hidden">{children}</div>
</>

View file

@ -0,0 +1,63 @@
import UserDataContext, { UserLang } from '../../context/UserDataContext';
import { useContext } from 'react';
import * as React from 'react';
const SidebarBottomButtons = ({ onContactUs }) => {
const languages = {
showAll: 'All',
cpp: 'C++',
java: 'Java',
py: 'Python',
};
const nextLang: { [key: string]: UserLang } = {
showAll: 'cpp',
cpp: 'java',
java: 'py',
py: 'cpp',
};
const userSettings = useContext(UserDataContext);
return (
<>
<div className="flex-shrink-0 border-t border-gray-200 flex">
<button
className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
onClick={() => userSettings.setLang(nextLang[userSettings.lang])}
>
<svg
className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
Language: {languages[userSettings.lang]}
</button>
</div>
<div className="flex-shrink-0 border-t border-gray-200 flex">
<button
className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"
onClick={onContactUs}
>
<svg
className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
</svg>
Contact Us
</button>
</div>
</>
);
};
export default SidebarBottomButtons;

View file

@ -0,0 +1,96 @@
import { Link } from 'gatsby';
import tw from 'twin.macro';
import * as React from 'react';
import styled from 'styled-components';
const LinkWithProgress = styled.span`
${tw`block relative`}
&::after {
content: '';
left: 24px;
top: 18px;
height: 8px;
width: 8px;
position: absolute;
transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1) 0s;
}
&::after {
border-radius: 100%;
${props => props.dotColorStyle};
}
&::before {
content: '';
position: absolute;
width: 2px;
display: block;
left: 27px;
top: 0;
bottom: 0;
${props => props.lineColorStyle};
}
&:first-of-type::before {
top: 22px;
}
&:last-of-type::before {
bottom: calc(100% - 22px);
}
`;
const StyledLink = styled.span`
${tw`focus:outline-none transition ease-in-out duration-150 hover:text-blue-700 hover:bg-blue-50 focus:bg-blue-100 flex items-center pl-12 pr-4 py-3 text-sm leading-5`}
${({ textStyle }) => textStyle}
&::before {
content: '';
left: 24px;
top: 18px;
height: 8px;
width: 8px;
position: absolute;
transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1) 0s;
}
&::before {
transform: ${({ isActive }) => (isActive ? 'scale(1)' : 'scale(0.1)')};
border-radius: 100%;
z-index: 1;
${({ dotColorStyle }) => dotColorStyle}
}
&:hover {
&::before {
transform: scale(1);
${tw`bg-blue-600`}
}
}
`;
export default function SidebarLink({
lineColorStyle,
dotColorStyle,
textStyle,
linkRef = null,
isActive,
url,
children,
}) {
return (
<LinkWithProgress
lineColorStyle={lineColorStyle}
dotColorStyle={dotColorStyle}
>
<Link to={url}>
<StyledLink isActive={isActive} ref={linkRef} textStyle={textStyle}>
{children}
</StyledLink>
</Link>
</LinkWithProgress>
);
}

243
src/pages/syllabus.tsx Normal file
View file

@ -0,0 +1,243 @@
import * as React from 'react';
import { PageProps } from 'gatsby';
import Layout from '../components/layout';
import SEO from '../components/seo';
import Sidebar, { SidebarLogo } from '../components/Sidebar/Sidebar';
import { useState } from 'react';
// @ts-ignore
import logo from '../assets/logo.svg';
import SidebarLink from '../components/Sidebar/SidebarLink';
import tw from 'twin.macro';
export default function SyllabusPage(props: PageProps) {
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
return (
<Layout>
<SEO title="Syllabus" />
<div className="h-screen flex overflow-hidden bg-gray-100">
<Sidebar
isMobileNavOpen={isMobileNavOpen}
onMobileNavStateChange={setIsMobileNavOpen}
mobileSidebarContent={<>todo</>}
desktopSidebarContent={
<>
<SidebarLink
url="/intro"
lineColorStyle={tw`bg-blue-700`}
dotColorStyle={tw`bg-blue-700`}
textStyle={tw`text-blue-700 font-medium`}
isActive={true}
>
Intro
</SidebarLink>
<SidebarLink
url="/intro"
lineColorStyle={tw`bg-gray-200`}
dotColorStyle={tw`bg-gray-200`}
textStyle={tw`font-medium`}
isActive={false}
>
Bronze
</SidebarLink>
<SidebarLink
url="/intro"
lineColorStyle={tw`bg-gray-200`}
dotColorStyle={tw`bg-gray-200`}
textStyle={tw`font-medium`}
isActive={false}
>
Silver
</SidebarLink>
<SidebarLink
url="/intro"
lineColorStyle={tw`bg-gray-200`}
dotColorStyle={tw`bg-gray-200`}
textStyle={tw`font-medium`}
isActive={false}
>
Gold
</SidebarLink>
<SidebarLink
url="/intro"
lineColorStyle={tw`bg-gray-200`}
dotColorStyle={tw`bg-gray-200`}
textStyle={tw`font-medium`}
isActive={false}
>
Platinum
</SidebarLink>
<SidebarLink
url="/intro"
lineColorStyle={tw`bg-gray-200`}
dotColorStyle={tw`bg-gray-200`}
textStyle={tw`font-medium`}
isActive={false}
>
Advanced
</SidebarLink>
</>
}
>
<div className="relative flex-shrink-0 flex h-16 bg-white shadow">
<button
className="px-4 border-r border-gray-200 text-gray-500 focus:outline-none focus:bg-gray-100 focus:text-gray-600 md:hidden"
aria-label="Open sidebar"
onClick={() => setIsMobileNavOpen(true)}
>
<svg
className="h-6 w-6"
stroke="currentColor"
fill="none"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h7"
/>
</svg>
</button>
<div className="flex-1 flex justify-between">
<div className="flex-1 flex ml-6">
<form className="w-full flex md:ml-0" action="#" method="GET">
<label htmlFor="search_field" className="sr-only">
Search
</label>
<div className="relative w-full text-gray-400 focus-within:text-gray-600">
<div className="absolute inset-y-0 left-0 flex items-center pointer-events-none">
<svg
className="h-5 w-5"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
/>
</svg>
</div>
<input
id="search_field"
className="block w-full h-full pl-8 pr-3 py-2 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400"
placeholder="Search"
type="search"
/>
</div>
</form>
</div>
<button
className="group border-l border-gray-200 px-4 sm:px-6 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:shadow-outline focus:text-gray-500 flex items-center transition duration-150 ease-in-out"
aria-label="Notifications"
>
<svg
className="h-6 w-6"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
<span className="text-gray-600 ml-3 font-medium group-hover:text-gray-800 hidden sm:block">
View Progress
</span>
</button>
</div>
</div>
<main
className="flex-1 relative z-0 overflow-y-auto focus:outline-none"
tabIndex={0}
>
<div className="flex pt-2 pb-6 md:py-6 px-4 sm:px-6 md:px-8 overflow-x-auto">
{/*<div className="bg-white shadow sm:rounded-lg w-full max-w-sm">*/}
{/* <div className="px-4 py-5 sm:p-6">*/}
{/* <h3 className="text-lg leading-6 font-medium text-gray-900">*/}
{/* Welcome to the USACO Guide!*/}
{/* </h3>*/}
{/* <div className="mt-2 max-w-xl text-sm leading-5 text-gray-500">*/}
{/* <p>*/}
{/* Get started on the first module, "Using this Guide."*/}
{/* </p>*/}
{/* </div>*/}
{/* <div className="mt-3 text-sm leading-5">*/}
{/* <a*/}
{/* href="#"*/}
{/* className="font-medium text-blue-600 hover:text-blue-500 transition ease-in-out duration-150"*/}
{/* >*/}
{/* Get Started! &rarr;*/}
{/* </a>*/}
{/* </div>*/}
{/* </div>*/}
{/*</div>*/}
<div className="bg-white shadow sm:rounded-lg w-full max-w-xl">
<div className="px-4 py-5 sm:p-6">
<h3 className="text-lg leading-6 font-medium text-gray-900">
Continue: Introduction to Competitive Programming
</h3>
<div className="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p>
Pick up where you left off. What is competitive
programming? Let's take a look!
</p>
</div>
<div className="mt-3 text-sm leading-5">
<a
href="#"
className="font-medium text-blue-600 hover:text-blue-500 transition ease-in-out duration-150"
>
Continue Module &rarr;
</a>
</div>
</div>
</div>
<div className="bg-white shadow sm:rounded-lg ml-6 w-full max-w-md">
<div className="px-4 py-5 sm:p-6">
<h3 className="text-lg leading-6 font-medium text-gray-900">
🔥 Six Day Streak: Keep it up!
</h3>
<div className="mt-2 max-w-xl text-sm leading-5 text-gray-500">
<p>You've visited this guide for six consecutive days.</p>
</div>
<div className="mt-3 text-sm leading-5">
<a
href="#"
className="font-medium text-blue-600 hover:text-blue-500 transition ease-in-out duration-150"
>
View Progress &rarr;
</a>
</div>
</div>
</div>
</div>
<div className="pt-2 pb-6 md:py-6 px-4 sm:px-6 md:px-8">
<h1 className="text-2xl font-semibold">1. About this Guide</h1>
{/* Replace with your content */}
<div className="py-4">
<div className="border-4 border-dashed border-gray-200 rounded-lg h-96" />
</div>
{/* /End replace */}
<h1 className="text-2xl font-semibold">2. Getting Started</h1>
{/* Replace with your content */}
<div className="py-4">
<div className="border-4 border-dashed border-gray-200 rounded-lg h-96" />
</div>
{/* /End replace */}
<h1 className="text-2xl font-semibold">1. About this Guide</h1>
{/* Replace with your content */}
<div className="py-4">
<div className="border-4 border-dashed border-gray-200 rounded-lg h-96" />
</div>
{/* /End replace */}
</div>
</main>
</Sidebar>
</div>
</Layout>
);
}