From 0d1cf9e4a0b91cd774499c3cc99cb2703ae17b19 Mon Sep 17 00:00:00 2001 From: Jerel Miller Date: Fri, 4 Sep 2020 02:10:38 -0700 Subject: [PATCH] feat: create an Agenda component to list sessions --- src/components/Agenda/Agenda.js | 60 ++++++++++++++++++ src/components/Agenda/Cell.js | 21 +++++++ src/components/Agenda/Heading.js | 38 +++++++++++ src/components/Agenda/Session.js | 50 +++++++++++++++ src/components/Agenda/Time.js | 11 ++++ src/components/Agenda/index.js | 1 + src/pages/nerd-days.js | 104 ++++++++++++++++++++++++++++++- src/pages/nerd-days.module.scss | 2 + 8 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 src/components/Agenda/Agenda.js create mode 100644 src/components/Agenda/Cell.js create mode 100644 src/components/Agenda/Heading.js create mode 100644 src/components/Agenda/Session.js create mode 100644 src/components/Agenda/Time.js create mode 100644 src/components/Agenda/index.js diff --git a/src/components/Agenda/Agenda.js b/src/components/Agenda/Agenda.js new file mode 100644 index 000000000..0b25b1e93 --- /dev/null +++ b/src/components/Agenda/Agenda.js @@ -0,0 +1,60 @@ +import React, { Children, Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { css } from '@emotion/core'; +import Heading from './Heading'; +import Session from './Session'; +import Time from './Time'; + +const Agenda = ({ children, className, tracks }) => { + const childrenArray = Children.toArray(children); + + const sessionsByTime = childrenArray + .filter((child) => child.type === Session) + .reduce((memo, child) => { + const { time } = child.props; + + return memo.set( + time, + memo.has(time) ? [...memo.get(time), child] : [child] + ); + }, new Map()); + + return ( +
+ + {tracks[0]} + + + {tracks.slice(1).map((track) => ( + {track} + ))} + + {Array.from(sessionsByTime).map(([time, sessions]) => ( + + + {sessions} + + ))} +
+ ); +}; + +Agenda.propTypes = { + className: PropTypes.string, + children: PropTypes.node, + tracks: PropTypes.arrayOf(PropTypes.string).isRequired, +}; + +Agenda.Session = Session; + +export default Agenda; diff --git a/src/components/Agenda/Cell.js b/src/components/Agenda/Cell.js new file mode 100644 index 000000000..b7d380969 --- /dev/null +++ b/src/components/Agenda/Cell.js @@ -0,0 +1,21 @@ +import PropTypes from 'prop-types'; +import styled from '@emotion/styled'; + +const Cell = styled.div` + padding: 1rem; + box-shadow: 0 0 0 1px var(--color-neutrals-400); + background-color: ${({ inactive }) => + inactive ? 'var(--color-neutrals-100)' : '#fff'}; + + .dark-mode & { + background-color: ${({ inactive }) => + inactive ? '#284049' : 'var(--color-dark-100)'}; + box-shadow: 0 0 0 1px var(--color-dark-400); + } +`; + +Cell.propTypes = { + inactive: PropTypes.bool, +}; + +export default Cell; diff --git a/src/components/Agenda/Heading.js b/src/components/Agenda/Heading.js new file mode 100644 index 000000000..36ee40f13 --- /dev/null +++ b/src/components/Agenda/Heading.js @@ -0,0 +1,38 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { css } from '@emotion/core'; +import Cell from './Cell'; + +const Heading = ({ children, className }) => ( + + {children} + +); + +Heading.propTypes = { + className: PropTypes.string, + children: PropTypes.node, +}; + +export default Heading; diff --git a/src/components/Agenda/Session.js b/src/components/Agenda/Session.js new file mode 100644 index 000000000..8ce5ef232 --- /dev/null +++ b/src/components/Agenda/Session.js @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { css } from '@emotion/core'; +import Cell from './Cell'; + +const Session = ({ inactive, time, speaker, title, span }) => ( + +

+ {title} +

+
+ {speaker} +
+
+); + +Session.propTypes = { + inactive: PropTypes.bool, + time: PropTypes.string, + speaker: PropTypes.string, + title: PropTypes.string, + span: PropTypes.number, +}; + +Session.defaultProps = { + span: 1, +}; + +export default Session; diff --git a/src/components/Agenda/Time.js b/src/components/Agenda/Time.js new file mode 100644 index 000000000..db3b422c9 --- /dev/null +++ b/src/components/Agenda/Time.js @@ -0,0 +1,11 @@ +import styled from '@emotion/styled'; +import Cell from './Cell'; + +const Time = styled(Cell)` + font-weight: 700; + display: flex; + align-items: center; + color: var(--heading-text-color); +`; + +export default Time; diff --git a/src/components/Agenda/index.js b/src/components/Agenda/index.js new file mode 100644 index 000000000..9671c4337 --- /dev/null +++ b/src/components/Agenda/index.js @@ -0,0 +1 @@ +export { default } from './Agenda'; diff --git a/src/pages/nerd-days.js b/src/pages/nerd-days.js index 91ee1b1e8..a89ed6875 100644 --- a/src/pages/nerd-days.js +++ b/src/pages/nerd-days.js @@ -21,6 +21,7 @@ import shapesIcon from '../images/nerd-days/icon-shapes.svg'; import openSourceIcon from '../images/nerd-days/icon-open-source.svg'; import HopinLogo from '../components/HopinLogo'; import styled from '@emotion/styled'; +import Agenda from '../components/Agenda'; const NerdDaysPage = () => { const { @@ -351,7 +352,106 @@ const NerdDaysPage = () => { respective industries -
+ + + + + + + + + + + + + + + + +
{
-
+