Skip to content

Commit 11640f3

Browse files
Mongolialadybbmoz
authored andcommitted
Application/#154707979 (#196)
* When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date) merge with master branch * When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date) * apply first * When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date) * apply second * When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date) * When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date) * When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date) * When mary log in and go to profile page, she will see a list of her own projects. When she click one, she will see the application detail(applicant's email and application date)
1 parent 6fbedc2 commit 11640f3

File tree

9 files changed

+119
-5
lines changed

9 files changed

+119
-5
lines changed

client/App.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import SignupForm from './components/SignupForm/SignupForm'
1515
import Version from './components/Version/Version'
1616
import LandingA from './components/LandingA/LandingA'
1717
import LandingC from './components/LandingC/LandingC'
18+
import ProjectDetail from './components/Project/ProjectDetail'
1819
import Footer from './components/LandingF/LandingF'
1920
import LandingB from './components/LandingB/LandingB'
2021

@@ -57,6 +58,7 @@ class App extends Component {
5758
<Route path='/landing-f' component={Footer} />
5859
<Route path='/landing-b' component={LandingB} />
5960
<Route path='/show-applications' component={ApplicationsRestrictedLoadable} />
61+
<Route path='/projects/:id' component={ProjectDetail} />
6062
</Switch>
6163
</div>
6264
)

client/actions/project/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,21 @@ export default class ProjectActionCreator {
6464
}
6565
}
6666
}
67+
68+
static fetchProjectById (id) {
69+
console.log('show applications 3')
70+
return (dispatch, getState) => {
71+
dispatch(ProjectActionCreator.fetching())
72+
73+
try {
74+
const state = getState()
75+
const apiOptions = apiOptionsFromState(state)
76+
const project = projectsApiClient.getProjectById(apiOptions, id)
77+
dispatch(ProjectActionCreator.received(project))
78+
} catch (e) {
79+
console.trace(e)
80+
dispatch(ProjectActionCreator.failed())
81+
}
82+
}
83+
}
6784
}

client/api/lib/apiRequest.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ async function apiRequest (apiOptions, options) {
2929

3030
function getQueryString (query = {}) {
3131
const encode = encodeURIComponent
32-
const keys = Object.keys(query)
32+
const keys = Object.keys(query || {})
3333

3434
return keys.length > 0
3535
? '?' + keys.map(k => encode(k) + '=' + encode(query[k])).join('&')

client/api/projects.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ const projectsApiClient = {
2424
body: JSON.stringify({ name, causes, technologies, organization })
2525
}
2626
return fetch('/api/projects/', options)
27+
},
28+
29+
getProjectById (apiOptions, id) {
30+
return apiRequest.get('/projects/' + id, apiOptions, null)
2731
}
2832
}
2933

client/components/Project/Project.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
22
import { connect } from 'react-redux'
33
import PropTypes from 'prop-types'
44
import Chip from 'material-ui/Chip'
5+
import {Link} from 'react-router-dom'
56
import styles from './Project.scss'
67

78
class Project extends Component {
@@ -62,7 +63,9 @@ class Project extends Component {
6263
onClick={this.handleClick.bind(this)}>
6364
<img className={styles.image} src={project.image || require('../../images/logo.png')} />
6465
<div className={styles.projectContent}>
65-
<div className={styles.projectTitle}>{project.name}</div>
66+
<div className={styles.projectTitle}>
67+
<Link to={`/projects/${project.id}`}>{project.name}</Link>
68+
</div>
6669
<div>{isContact && isProfile ? null : project.organization.name || 'Organization Name'}</div>
6770
<div>{this.renderProjectApplicationResult(project)}</div>
6871
</div>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React, { Component } from 'react'
2+
import { connect } from 'react-redux'
3+
import ProjectActionCreator from '../../actions/project'
4+
import PropTypes from 'prop-types'
5+
import {Link} from 'react-router-dom'
6+
import Card, {CardContent} from 'material-ui/Card'
7+
import Typography from 'material-ui/Typography'
8+
import styles from './ProjectDetail.scss'
9+
10+
class ProjectDetail extends Component {
11+
constructor (args) {
12+
super(args)
13+
this.state = {projectId: this.props.match.params.id}
14+
}
15+
16+
componentDidMount () {
17+
this.props.fetchProjectById(this.state.projectId)
18+
}
19+
20+
renderApplication (application) {
21+
return (
22+
<Card>
23+
<CardContent>
24+
<Typography>
25+
Applicant: {application.volunteer.email}
26+
</Typography>
27+
<Typography expandable={true}>
28+
Message: {application.message}
29+
</Typography>
30+
<Typography>
31+
Submitted at: {application.createdAt}
32+
</Typography>
33+
</CardContent>
34+
</Card>
35+
)
36+
}
37+
38+
render () {
39+
const project = this.props.project || {}
40+
const applications = project.applications || []
41+
return applications.length === 0 ? (
42+
<div>
43+
<h1>No one had applied this project</h1>
44+
<p className={styles.goBack}>
45+
<Link to={`/profile`}>Go Back</Link>
46+
</p>
47+
</div>) : (
48+
<div>
49+
<h1>The following applicants applied this project:</h1>
50+
<ul>
51+
{
52+
applications.map((app) => <li key={app.id}> {this.renderApplication(app)} </li>)
53+
}
54+
</ul>
55+
<p className={styles.goBack}>
56+
<Link to={`/profile`} >Go Back</Link>
57+
</p>
58+
</div>)
59+
}
60+
}
61+
62+
const mapDispatchToProps = {
63+
fetchProjectById: ProjectActionCreator.fetchProjectById
64+
}
65+
66+
const mapStateToProperties = (state) => {
67+
return {project: state.project.project || {}}
68+
}
69+
70+
ProjectDetail.propTypes = {
71+
project: PropTypes.object,
72+
fetchProjectById: PropTypes.func,
73+
match: PropTypes.object
74+
}
75+
76+
export default connect(mapStateToProperties, mapDispatchToProps)(ProjectDetail)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import '../../scss/partials/partials';
2+
3+
.goBack {
4+
margin-top: 20px;
5+
}

client/reducers/projectReducer.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ export default function (state = initialState.projects, action) {
1313
return { ...state, fetching: true }
1414

1515
case RECEIVED_PROJECTS:
16-
return { ...state, fetching: false, projects: payload }
16+
const value = payload || {}
17+
if (value instanceof Array) {
18+
return {...state, fetching: false, projects: payload}
19+
} else {
20+
return {...state, fetching: false, project: payload}
21+
}
1722

1823
case FAILED_PROJECTS:
1924
return { ...state, fetching: false }

server/routes/controllers/projects.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ export default {
5252
},
5353

5454
async projectById (req, res, next, id) {
55-
const project = await this.Projects.findById(id)
56-
55+
const project = await this.Projects.findById(id).populate({
56+
path: 'applications',
57+
populate: {path: 'volunteer'}
58+
})
5759
if (!project) throw new NotFoundError()
5860

5961
req.project = project

0 commit comments

Comments
 (0)