|
@@ -0,0 +1,242 @@
|
|
|
+function calculateRating (ratings) {
|
|
|
+ const numberOfRatings = ratings.length
|
|
|
+ const sumOfRatings = ratings.reduce(
|
|
|
+ (accumulator, rating) => accumulator + rating.value,
|
|
|
+ 0
|
|
|
+ )
|
|
|
+ return numberOfRatings ? sumOfRatings / numberOfRatings : '-'
|
|
|
+}
|
|
|
+
|
|
|
+const TrainingArchive = props => (
|
|
|
+ <div>
|
|
|
+ <h2>Training Archive</h2>
|
|
|
+ <ol>
|
|
|
+ {props.trainings.map(training => (
|
|
|
+ <TrainingHint key={training.id} training={training} />
|
|
|
+ ))}
|
|
|
+ </ol>
|
|
|
+ </div>
|
|
|
+)
|
|
|
+
|
|
|
+const TrainingHint = props => (
|
|
|
+ <div>
|
|
|
+ <div>{props.training.date}</div>
|
|
|
+ <div>{props.training.title}</div>
|
|
|
+ </div>
|
|
|
+)
|
|
|
+
|
|
|
+const Training = props => (
|
|
|
+ <article>
|
|
|
+ <h2>{props.title}</h2>
|
|
|
+ <aside>
|
|
|
+ <div id='trainingType'>
|
|
|
+ <span className='caption'>Type: </span>
|
|
|
+ <span className='data'>{props.type.name}</span>
|
|
|
+ </div>
|
|
|
+ <div id='trainingDate'>
|
|
|
+ <span className='caption'>Date: </span>
|
|
|
+ <span className='data'>
|
|
|
+ {new Date(props.trainingDate).toLocaleDateString()}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div id='trainingLocation'>
|
|
|
+ <span className='caption'>Location: </span>
|
|
|
+ <span className='data'>{props.location}</span>
|
|
|
+ </div>
|
|
|
+ <div id='trainingRegistrations'>
|
|
|
+ <span className='caption'>Registrations: </span>
|
|
|
+ <span className='data'>
|
|
|
+ {props.registration.length} <a href=''>Register!</a>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div id='trainingAttendance'>
|
|
|
+ <span className='caption'>Attendance: </span>
|
|
|
+ <span className='data'>{props.attendance}</span>
|
|
|
+ </div>
|
|
|
+ <div id='trainingRatings'>
|
|
|
+ <span className='caption'>Rating: </span>
|
|
|
+ <span className='data'>
|
|
|
+ {calculateRating(props.ratings)} [
|
|
|
+ <a href=''>{props.ratings.length}</a>] Rate it!
|
|
|
+ <a href=''>*</a>
|
|
|
+ <a href=''>*</a>
|
|
|
+ <a href=''>*</a>
|
|
|
+ <a href=''>*</a>
|
|
|
+ <a href=''>*</a>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </aside>
|
|
|
+ <section>
|
|
|
+ <h3>Content</h3>
|
|
|
+ <ol>
|
|
|
+ {props.content
|
|
|
+ .sort(block => block.sequence)
|
|
|
+ .map(block => (
|
|
|
+ <Block key={block.id} {...block} />
|
|
|
+ ))}
|
|
|
+ </ol>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <style jsx>
|
|
|
+ {`
|
|
|
+ article {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr 3fr;
|
|
|
+
|
|
|
+ background-color: rgba(127, 127, 127, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ article > h2 {
|
|
|
+ font-weight: 900;
|
|
|
+ font-size: 120%;
|
|
|
+ }
|
|
|
+
|
|
|
+ aside {
|
|
|
+ padding: 1em 2em;
|
|
|
+ background: rgba(0, 127, 0, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ section {
|
|
|
+ padding: 1em 2em;
|
|
|
+ background: rgba(127, 0, 0, 0.5);
|
|
|
+ }
|
|
|
+ `}
|
|
|
+ </style>
|
|
|
+ </article>
|
|
|
+)
|
|
|
+
|
|
|
+const Youtube = props => {
|
|
|
+ const { link, rest } = props
|
|
|
+ const [crap, src] = props.link.match(/\?v=(.*)/)
|
|
|
+ return (
|
|
|
+ <iframe
|
|
|
+ width='285'
|
|
|
+ height='160'
|
|
|
+ src={`https://www.youtube.com/embed/${src}`}
|
|
|
+ frameBorder='0'
|
|
|
+ allow='accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'
|
|
|
+ allowFullScreen
|
|
|
+ {...rest}
|
|
|
+ />
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const Spotify = props => {
|
|
|
+ const { link, rest } = props
|
|
|
+ const [crap, src] = props.link.match(/track\/(.*)/)
|
|
|
+ return (
|
|
|
+ <iframe
|
|
|
+ src={`https://open.spotify.com/embed/track/${src}`}
|
|
|
+ width='300'
|
|
|
+ height='80'
|
|
|
+ frameborder='0'
|
|
|
+ allowtransparency='true'
|
|
|
+ allow='encrypted-media'
|
|
|
+ />
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const Media = props => {
|
|
|
+ if (props.link.includes('youtube.com')) {
|
|
|
+ return <Youtube {...props} />
|
|
|
+ } else if (props.link.includes('spotify.com')) {
|
|
|
+ return <Spotify {...props} />
|
|
|
+ } else {
|
|
|
+ return <p>Link not recognized.</p>
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const Block = props => (
|
|
|
+ <li>
|
|
|
+ <h2>{props.title}</h2>
|
|
|
+ <p>
|
|
|
+ <span className='caption'>Duration: </span>
|
|
|
+ <span className='data'>{props.duration}</span>
|
|
|
+ </p>
|
|
|
+ <p>
|
|
|
+ <span className='caption'>Variation: </span>
|
|
|
+ <span className='data'>{props.variation}</span>
|
|
|
+ </p>
|
|
|
+ <p>
|
|
|
+ <span className='caption'>Description: </span>
|
|
|
+ <span className='data'>{props.description}</span>
|
|
|
+ </p>
|
|
|
+ <p>
|
|
|
+ <span className='caption'>Format: </span>
|
|
|
+ <span className='data'>
|
|
|
+ {props.format.name}{' '}
|
|
|
+ <sup>
|
|
|
+ <a title={props.format.description}>[?]</a>
|
|
|
+ </sup>
|
|
|
+ </span>
|
|
|
+ </p>
|
|
|
+ <section>
|
|
|
+ <h2>Tracks</h2>
|
|
|
+ <ol>
|
|
|
+ {props.tracks.map(track => (
|
|
|
+ <Track key={track.id} {...track} />
|
|
|
+ ))}
|
|
|
+ </ol>
|
|
|
+ </section>
|
|
|
+ <section>
|
|
|
+ <h2>Exercises</h2>
|
|
|
+ <ol>
|
|
|
+ {props.exercises.map(exercise => (
|
|
|
+ <Exercise key={exercise.id} {...exercise} />
|
|
|
+ ))}
|
|
|
+ </ol>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <style jsx>
|
|
|
+ {`
|
|
|
+ section {
|
|
|
+ display: grid;
|
|
|
+ }
|
|
|
+ `}
|
|
|
+ </style>
|
|
|
+ </li>
|
|
|
+)
|
|
|
+
|
|
|
+const Track = props => {
|
|
|
+ return (
|
|
|
+ <section>
|
|
|
+ <p>
|
|
|
+ Track {props.id}: {props.title} ({props.artist})
|
|
|
+ </p>
|
|
|
+ <Media link={props.link} />
|
|
|
+ </section>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const Exercise = props => {
|
|
|
+ return (
|
|
|
+ <section>
|
|
|
+ <p>
|
|
|
+ Exercise {props.id}: {props.name}
|
|
|
+ </p>
|
|
|
+ </section>
|
|
|
+ )
|
|
|
+}
|
|
|
+class TrainingCreateForm extends React.Component {
|
|
|
+ render () {
|
|
|
+ return (
|
|
|
+ <form>
|
|
|
+ <label htmlFor='title'>
|
|
|
+ Title
|
|
|
+ <input type='text' id='title' />
|
|
|
+ </label>
|
|
|
+ <label htmlFor='title'>
|
|
|
+ Title
|
|
|
+ <input type='text' id='title' />
|
|
|
+ </label>
|
|
|
+ <label htmlFor='title'>
|
|
|
+ Title
|
|
|
+ <input type='text' id='title' />
|
|
|
+ </label>
|
|
|
+ </form>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export { TrainingArchive }
|
|
|
+export default Training
|