Break up map components
Add static super blocks
This commit is contained in:
82
common/app/routes/map/components/Block.jsx
Normal file
82
common/app/routes/map/components/Block.jsx
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import FA from 'react-fontawesome';
|
||||||
|
import PureComponent from 'react-pure-render/component';
|
||||||
|
import { Panel } from 'react-bootstrap';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
|
||||||
|
export default class Block extends PureComponent {
|
||||||
|
static displayName = 'Block';
|
||||||
|
static propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
time: PropTypes.string,
|
||||||
|
challenges: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
renderChallenges(challenges) {
|
||||||
|
if (!Array.isArray(challenges) || !challenges.length) {
|
||||||
|
return <div>No Challenges Found</div>;
|
||||||
|
}
|
||||||
|
return challenges.map(challenge => {
|
||||||
|
const { title, dashedName, isLocked, isRequired } = challenge;
|
||||||
|
const challengeClassName = classnames({
|
||||||
|
'text-primary': true,
|
||||||
|
'padded-ionic-icon': true,
|
||||||
|
'negative-15': true,
|
||||||
|
'challenge-title': true,
|
||||||
|
'ion-checkmark-circled': !isLocked,
|
||||||
|
'ion-locked': isLocked,
|
||||||
|
'disabled': isLocked
|
||||||
|
});
|
||||||
|
if (isLocked) {
|
||||||
|
return (
|
||||||
|
<p
|
||||||
|
className={ challengeClassName }
|
||||||
|
key={ title }>
|
||||||
|
{ title }
|
||||||
|
{
|
||||||
|
isRequired ?
|
||||||
|
<span className='text-primary'><strong>*</strong></span> :
|
||||||
|
''
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<p
|
||||||
|
className={ challengeClassName }
|
||||||
|
key={ title }>
|
||||||
|
<a href={ `/challenges/${dashedName}` }>
|
||||||
|
{ title }
|
||||||
|
<span className='sr-only'>complete</span>
|
||||||
|
{
|
||||||
|
isRequired ?
|
||||||
|
<span className='text-primary'><strong>*</strong></span> :
|
||||||
|
''
|
||||||
|
}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { title, time, challenges } = this.props;
|
||||||
|
return (
|
||||||
|
<Panel
|
||||||
|
bsClass='map-accordion-panel-nested'
|
||||||
|
collapsible={ true }
|
||||||
|
expanded={ true }
|
||||||
|
header={
|
||||||
|
<div>
|
||||||
|
<h3><FA name='caret-right' />{ title }</h3>
|
||||||
|
<span className='challenge-block-time'>({ time })</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
id={ title }
|
||||||
|
key={ title }>
|
||||||
|
{ this.renderChallenges(challenges) }
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
61
common/app/routes/map/components/Coding-Prep.jsx
Normal file
61
common/app/routes/map/components/Coding-Prep.jsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PureComponent from 'react-pure-render/component';
|
||||||
|
import dedent from 'dedent';
|
||||||
|
import SuperBlock from './Super-Block.jsx';
|
||||||
|
|
||||||
|
const lockMessage = dedent`
|
||||||
|
To qualify for these nonprofit projects,
|
||||||
|
you must first earn all three foundational certifications:
|
||||||
|
Front End, Data Visualization, and Back End
|
||||||
|
`.replace(/[\n]/g, ' ');
|
||||||
|
|
||||||
|
const codingPrep = [{
|
||||||
|
title: 'Coding Interview Training',
|
||||||
|
time: '70 Hours',
|
||||||
|
challenges: [
|
||||||
|
{
|
||||||
|
title: 'Soft Skill Training',
|
||||||
|
isLocked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Critical Thinking Training',
|
||||||
|
isLocked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Whiteboard Coding Training',
|
||||||
|
isLocked: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
title: 'Mock Interviews',
|
||||||
|
time: '10 Hours',
|
||||||
|
challenges: [
|
||||||
|
{
|
||||||
|
title: 'Mock Interview #1',
|
||||||
|
isLocked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mock Interview #2',
|
||||||
|
isLocked: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mock Interview #3',
|
||||||
|
isLocked: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
|
export default class CodingPrep extends PureComponent {
|
||||||
|
static displayName = 'CodingPrep;'
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SuperBlock
|
||||||
|
blocks={ codingPrep }
|
||||||
|
message={ lockMessage }
|
||||||
|
title='Coding Interview Prep ' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
54
common/app/routes/map/components/Full-Stack.jsx
Normal file
54
common/app/routes/map/components/Full-Stack.jsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PureComponent from 'react-pure-render/component';
|
||||||
|
import dedent from 'dedent';
|
||||||
|
import SuperBlock from './Super-Block.jsx';
|
||||||
|
|
||||||
|
const lockMessage = dedent`
|
||||||
|
To qualify for these nonprofit projects,
|
||||||
|
you must first earn all three foundational certifications:
|
||||||
|
Front End, Data Visualization, and Back End
|
||||||
|
`.replace(/[\n]/g, ' ');
|
||||||
|
|
||||||
|
const nonprofitProjects = {
|
||||||
|
title: 'Nonprofit Projects',
|
||||||
|
time: '800 Hours',
|
||||||
|
challenges: [
|
||||||
|
{
|
||||||
|
title: 'Greenfield Nonprofit Project #1',
|
||||||
|
isLocked: true,
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Greenfield Nonprofit Project #2',
|
||||||
|
isLocked: true,
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Legacy Code Nonprofit Project #1',
|
||||||
|
isLocked: true,
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Legacy Code Nonprofit Project #2',
|
||||||
|
isLocked: true,
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Claim your Full Stack Development Certification',
|
||||||
|
isLocked: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class FullStack extends PureComponent {
|
||||||
|
static displayName = 'FullStack';
|
||||||
|
render() {
|
||||||
|
const title = 'Full Stack Development Certification';
|
||||||
|
return (
|
||||||
|
<SuperBlock
|
||||||
|
blocks={ [ nonprofitProjects ] }
|
||||||
|
message={ lockMessage }
|
||||||
|
title={ title } />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,10 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import FA from 'react-fontawesome';
|
|
||||||
import PureComponent from 'react-pure-render/component';
|
import PureComponent from 'react-pure-render/component';
|
||||||
import {
|
import { Input, Button, Row } from 'react-bootstrap';
|
||||||
Input,
|
|
||||||
Button,
|
|
||||||
Row,
|
|
||||||
Panel
|
|
||||||
} from 'react-bootstrap';
|
|
||||||
|
|
||||||
const challengeClassName = `
|
import SuperBlock from './Super-Block.jsx';
|
||||||
text-primary
|
import FullStack from './Full-Stack.jsx';
|
||||||
padded-ionic-icon
|
import CodingPrep from './Coding-Prep.jsx';
|
||||||
negative-15
|
|
||||||
challenge-title
|
|
||||||
ion-checkmark-circled
|
|
||||||
`.replace(/[\n]/g, '');
|
|
||||||
|
|
||||||
export default class ShowMap extends PureComponent {
|
export default class ShowMap extends PureComponent {
|
||||||
static displayName = 'Map';
|
static displayName = 'Map';
|
||||||
@ -22,69 +12,15 @@ export default class ShowMap extends PureComponent {
|
|||||||
superBlocks: PropTypes.array
|
superBlocks: PropTypes.array
|
||||||
};
|
};
|
||||||
|
|
||||||
renderChallenges(challenges) {
|
|
||||||
if (!Array.isArray(challenges) || !challenges.length) {
|
|
||||||
return <div>No Challenges Found</div>;
|
|
||||||
}
|
|
||||||
return challenges.map(challenge => {
|
|
||||||
const { title, dashedName } = challenge;
|
|
||||||
return (
|
|
||||||
<p
|
|
||||||
className={ challengeClassName }
|
|
||||||
key={ title }>
|
|
||||||
<a href={ `/challenges/${dashedName}` }>
|
|
||||||
{ title }
|
|
||||||
<span className='sr-only'>complete</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBlocks(blocks) {
|
|
||||||
if (!Array.isArray(blocks) || !blocks.length) {
|
|
||||||
return <div>No Blocks Found</div>;
|
|
||||||
}
|
|
||||||
return blocks.map(block => {
|
|
||||||
const { title, time, challenges } = block;
|
|
||||||
return (
|
|
||||||
<Panel
|
|
||||||
bsClass='map-accordion-panel-nested'
|
|
||||||
collapsible={ true }
|
|
||||||
expanded={ true }
|
|
||||||
header={
|
|
||||||
<div>
|
|
||||||
<h3><FA name='caret-right' />{ title }</h3>
|
|
||||||
<span className='challenge-block-time'>({ time })</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
id={ title }
|
|
||||||
key={ title }>
|
|
||||||
{ this.renderChallenges(challenges) }
|
|
||||||
</Panel>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSuperBlocks(superBlocks) {
|
renderSuperBlocks(superBlocks) {
|
||||||
if (!Array.isArray(superBlocks) || !superBlocks.length) {
|
if (!Array.isArray(superBlocks) || !superBlocks.length) {
|
||||||
return <div>No Super Blocks</div>;
|
return <div>No Super Blocks</div>;
|
||||||
}
|
}
|
||||||
return superBlocks.map((superBlock) => {
|
return superBlocks.map((superBlock) => {
|
||||||
const { title, blocks } = superBlock;
|
|
||||||
return (
|
return (
|
||||||
<Panel
|
<SuperBlock
|
||||||
bsClass='map-accordion-panel'
|
key={ superBlock.title }
|
||||||
collapsible={ true }
|
{ ...superBlock }/>
|
||||||
expanded={ true }
|
|
||||||
header={ <h2><FA name='caret-right' />{ title }</h2> }
|
|
||||||
id={ title }
|
|
||||||
key={ title }>
|
|
||||||
<div
|
|
||||||
className='map-accordion-block'>
|
|
||||||
{ this.renderBlocks(blocks) }
|
|
||||||
</div>
|
|
||||||
</Panel>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -120,6 +56,8 @@ export default class ShowMap extends PureComponent {
|
|||||||
<div
|
<div
|
||||||
className='map-accordion'>
|
className='map-accordion'>
|
||||||
{ this.renderSuperBlocks(superBlocks) }
|
{ this.renderSuperBlocks(superBlocks) }
|
||||||
|
<FullStack />
|
||||||
|
<CodingPrep />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
53
common/app/routes/map/components/Super-Block.jsx
Normal file
53
common/app/routes/map/components/Super-Block.jsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import PureComponent from 'react-pure-render/component';
|
||||||
|
import FA from 'react-fontawesome';
|
||||||
|
import { Panel } from 'react-bootstrap';
|
||||||
|
|
||||||
|
import Block from './Block.jsx';
|
||||||
|
|
||||||
|
export default class SuperBlock extends PureComponent {
|
||||||
|
static displayName = 'SuperBlock';
|
||||||
|
static propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
message: PropTypes.string,
|
||||||
|
blocks: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
renderBlocks(blocks) {
|
||||||
|
if (!Array.isArray(blocks) || !blocks.length) {
|
||||||
|
return <div>No Blocks Found</div>;
|
||||||
|
}
|
||||||
|
return blocks.map(block => {
|
||||||
|
return (
|
||||||
|
<Block
|
||||||
|
key={ block.title }
|
||||||
|
{ ...block } />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { title, blocks, message } = this.props;
|
||||||
|
return (
|
||||||
|
<Panel
|
||||||
|
bsClass='map-accordion-panel'
|
||||||
|
collapsible={ true }
|
||||||
|
expanded={ true }
|
||||||
|
header={ <h2><FA name='caret-right' />{ title }</h2> }
|
||||||
|
id={ title }
|
||||||
|
key={ title }>
|
||||||
|
{
|
||||||
|
message ?
|
||||||
|
<div className='challenge-block-description'>
|
||||||
|
{ message }
|
||||||
|
</div> :
|
||||||
|
''
|
||||||
|
}
|
||||||
|
<div
|
||||||
|
className='map-accordion-block'>
|
||||||
|
{ this.renderBlocks(blocks) }
|
||||||
|
</div>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user