training.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import theme from '../../styles/theme'
  2. import PropTypes from 'prop-types'
  3. import TrainingType from './trainingType'
  4. import TrainingBlock from './trainingBlock'
  5. function calculateRating (ratings) {
  6. const numberOfRatings = ratings.length
  7. const sumOfRatings = ratings.reduce(
  8. (accumulator, rating) => accumulator + rating.value,
  9. 0
  10. )
  11. return numberOfRatings ? sumOfRatings / numberOfRatings : '-'
  12. }
  13. const Training = props => (
  14. <article>
  15. <h2>{props.title}</h2>
  16. <aside>
  17. <div id='trainingType'>
  18. <span className='caption'>Type: </span>
  19. <span className='data'>{props.type.name}</span>
  20. </div>
  21. <div id='trainingDate'>
  22. <span className='caption'>Date: </span>
  23. <span className='data'>
  24. {new Date(props.trainingDate).toLocaleDateString()}
  25. </span>
  26. </div>
  27. <div id='trainingLocation'>
  28. <span className='caption'>Location: </span>
  29. <span className='data'>{props.location}</span>
  30. </div>
  31. <div id='trainingRegistrations'>
  32. <span className='caption'>Registrations: </span>
  33. <span className='data'> {props.registration.length} </span>
  34. </div>
  35. <div id='trainingAttendance'>
  36. <span className='caption'>Attendance: </span>
  37. <span className='data'>{props.attendance}</span>
  38. </div>
  39. <div id='trainingRatings'>
  40. <span className='caption'>Rating: </span>
  41. <span className='data'>
  42. {calculateRating(props.ratings)} [
  43. <a href=''>{props.ratings.length}</a>] Rate it!
  44. <a href=''>*</a>
  45. <a href=''>*</a>
  46. <a href=''>*</a>
  47. <a href=''>*</a>
  48. <a href=''>*</a>
  49. </span>
  50. </div>
  51. <button>Register now!</button>
  52. </aside>
  53. <section>
  54. <h3>Content</h3>
  55. <ol>
  56. {props.content
  57. .sort(block => block.sequence)
  58. .map(block => (
  59. <TrainingBlock key={block.id} {...block} />
  60. ))}
  61. </ol>
  62. </section>
  63. <style jsx>
  64. {`
  65. article {
  66. display: grid;
  67. grid-template-areas:
  68. 'title title'
  69. 'information placeholder'
  70. 'content content';
  71. grid-template-columns: 1fr 2fr;
  72. background-color: rgba(127, 127, 127, 0.5);
  73. background-image: url('media/man_working_out.jpg');
  74. background-size: auto 400px;
  75. background-repeat: no-repeat;
  76. margin: 2em 0;
  77. }
  78. article > * {
  79. padding: 0.2em 1em;
  80. }
  81. article > h2 {
  82. grid-area: title;
  83. font-weight: 900;
  84. font-size: 120%;
  85. background: ${theme.colors.darkerblue};
  86. color: ${theme.colors.offWhite};
  87. }
  88. aside {
  89. grid-area: information;
  90. background: rgba(0, 127, 0, 0.5);
  91. padding: 1em 2em;
  92. margin: 0 1em;
  93. min-height: 350px;
  94. }
  95. section {
  96. grid-area: content;
  97. padding: 1em 2em;
  98. background: rgba(127, 0, 0, 0.5);
  99. }
  100. span.caption {
  101. display: none;
  102. }
  103. `}
  104. </style>
  105. </article>
  106. )
  107. Training.propTypes = {
  108. title: PropTypes.string.isRequired,
  109. type: PropTypes.shape(TrainingType.propTypes).isRequired,
  110. content: PropTypes.arrayOf(TrainingBlock.propTypes).isRequired,
  111. createdAt: PropTypes.number,
  112. trainingDate: PropTypes.number.isRequired,
  113. location: PropTypes.string.isRequired,
  114. registration: PropTypes
  115. }
  116. export default Training