diff --git a/common/app/routes/challenges/components/Show.jsx b/common/app/routes/challenges/components/Show.jsx
index 16e5948099..ae3e7f3e6f 100644
--- a/common/app/routes/challenges/components/Show.jsx
+++ b/common/app/routes/challenges/components/Show.jsx
@@ -7,12 +7,15 @@ import PureComponent from 'react-pure-render/component';
import Classic from './classic/Classic.jsx';
import Step from './step/Step.jsx';
+import Project from './project/Project.jsx';
+
import { fetchChallenge, fetchChallenges } from '../redux/actions';
import { challengeSelector } from '../redux/selectors';
const views = {
step: Step,
- classic: Classic
+ classic: Classic,
+ project: Project
};
const bindableActions = {
diff --git a/common/app/routes/challenges/components/project/Project.jsx b/common/app/routes/challenges/components/project/Project.jsx
new file mode 100644
index 0000000000..106b3066d1
--- /dev/null
+++ b/common/app/routes/challenges/components/project/Project.jsx
@@ -0,0 +1,174 @@
+import React, { PropTypes } from 'react';
+import { createSelector } from 'reselect';
+import { connect } from 'react-redux';
+
+import Youtube from 'react-youtube';
+import PureComponent from 'react-pure-render/component';
+import { Button, ButtonGroup, Col, Row } from 'react-bootstrap';
+
+import { challengeSelector } from '../../redux/selectors';
+
+const bindableActions = {};
+
+const mapStateToProps = createSelector(
+ challengeSelector,
+ state => state.app.windowHeight,
+ state => state.app.navHeight,
+ state => state.app.isSignedIn,
+ state => state.challengesApp.tests,
+ state => state.challengesApp.output,
+ (
+ {
+ challenge: {
+ id,
+ title,
+ description,
+ challengeSeed: [ videoId = ''] = []
+ } = {}
+ },
+ windowHeight,
+ navHeight,
+ isSignedIn,
+ tests,
+ output
+ ) => ({
+ id,
+ videoId,
+ title,
+ description,
+ height: windowHeight - navHeight - 20,
+ tests,
+ output,
+ isSignedIn
+ })
+);
+
+export class Project extends PureComponent {
+ static displayName = 'Project';
+ static propTypes = {
+ id: PropTypes.string,
+ videoId: PropTypes.string,
+ title: PropTypes.string,
+ description: PropTypes.arrayOf(PropTypes.string),
+ isCompleted: PropTypes.bool,
+ isSignedIn: PropTypes.bool
+ };
+
+ renderIcon(isCompleted) {
+ if (!isCompleted) {
+ return null;
+ }
+ return (
+
+ );
+ }
+
+ renderDescription(title = '', description = []) {
+ return description
+ .map((line, index) => (
+