Skip to content

Commit ec749a2

Browse files
committed
Move timetable local state to Redux store
1 parent 5351a93 commit ec749a2

File tree

12 files changed

+303
-75
lines changed

12 files changed

+303
-75
lines changed

meetingapp/app/actions/timetable.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Defines actions related to timetable.
3+
*
4+
* This approach is refered from Redux creator - gaearon's comments :
5+
* https://github.com/rackt/redux/issues/291
6+
*/
7+
import Parse from '../modules/parse/index';
8+
9+
export const REQUEST_SET_AVAILABLE_TIME = 'REQUEST_SET_AVAILABLE_TIME';
10+
export function requestSetAvailableTime() {
11+
return {
12+
type: REQUEST_SET_AVAILABLE_TIME,
13+
payload: {}
14+
}
15+
}
16+
17+
export const CANCEL_SET_AVAILABLE_TIME = 'CANCEL_SET_AVAILABLE_TIME';
18+
export function cancelSetAvailableTime() {
19+
return {
20+
type: CANCEL_SET_AVAILABLE_TIME,
21+
payload: {}
22+
}
23+
}
24+
25+
export const SET_AVAILABLE_TIME = 'SET_AVAILABLE_TIME';
26+
export function setAvailableTime(row, col) {
27+
return {
28+
type: SET_AVAILABLE_TIME,
29+
payload: { row, col }
30+
}
31+
}

meetingapp/app/components/Timetable/Timetable.css

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
1010
padding: 2px;
1111
color: rgba(0,0,0,0.8);
12-
transition: all 0.2s ease-in-out;
13-
}
14-
15-
.timetable:hover {
16-
box-shadow: 0 10px 3px rgba(0,0,0,0.12), 0 1px 8px rgba(0,0,0,0.24);
1712
}
1813

1914
.timetable thead th {
@@ -38,7 +33,7 @@
3833
transition: all 0.3s;
3934
}
4035

41-
.timetable td.unavailable:hover {
36+
.timetable.settable td.unavailable:hover {
4237
background-color: #dcdcdc;
4338
color: white;
4439
}
Lines changed: 53 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { Component, PropTypes } from 'react';
2+
import * as TimetableActions from '../../actions/timetable';
23
import classnames from 'classnames';
34
import styles from './Timetable.css';
45

@@ -7,68 +8,26 @@ export default class Timetable extends Component {
78
/* we can init state here */
89
constructor(props) {
910
super(props);
10-
11-
this.state = {
12-
timetable: this.initTimetable()
13-
}
14-
}
15-
16-
initTimetable = () => {
17-
18-
/* props */
19-
const {days, start, end, diff} = this.props;
20-
21-
/**
22-
* timetable @type {Object Array} every time slots from starting hour to ending hour
23-
* [
24-
* {
25-
* start, # @type {number} [start hour]
26-
* end, # @type {number} [start hour + diff]
27-
* cells: # @type {array} [every day in weeks, e.g. cells[0] = Mon, cells[1] = Tue ...]
28-
* {
29-
* available # @type {boolean} [user at this time is available or not]
30-
* }
31-
* }
32-
* ]
33-
*/
34-
let timetable = [];
35-
36-
for (let i = start ; i < end ; i += diff) {
37-
38-
let cells = [];
39-
40-
for (let day in days) {
41-
cells.push({ available: false });
42-
}
43-
44-
timetable.push({
45-
start: i,
46-
end: i + diff,
47-
cells: cells
48-
});
49-
}
50-
51-
return timetable;
11+
console.log(props);
5212
}
5313

54-
handleSetAvailable = (rowIndex, colIndex) => {
55-
56-
let timetable = Object.assign([], this.state.timetable);
14+
handleSetAvailableTime = (row, col) => {
15+
16+
const { isSetting, onSetAvailableTime } = this.props;
5717

58-
timetable[rowIndex].cells[colIndex].available = !timetable[rowIndex].cells[colIndex].available;
59-
60-
this.setState({
61-
timetable: timetable
62-
});
18+
if (isSetting)
19+
onSetAvailableTime(row, col);
6320
}
6421

6522
render() {
6623

6724
/* props */
68-
const { days } = this.props;
25+
const { days, timetable, settable } = this.props;
6926

7027
return (
71-
<table className={styles.timetable}>
28+
<table className={classnames(styles.timetable, {
29+
[`${styles.settable}`]: settable
30+
})}>
7231
<thead>
7332
<tr>
7433
<th>Time</th>
@@ -78,7 +37,7 @@ export default class Timetable extends Component {
7837
</tr>
7938
</thead>
8039
<tbody>
81-
{this.state.timetable.map((row, rowIndex) =>
40+
{timetable.map((row, rowIndex) =>
8241
<tr key={rowIndex}>
8342
<th>{`${row.start}:00 - ${row.end}:00`}</th>
8443
{row.cells.map((cell, colIndex) => (
@@ -88,7 +47,7 @@ export default class Timetable extends Component {
8847
[`${styles.unavailable}`]: !cell.available,
8948
}
9049
)}
91-
onClick={(e) => this.handleSetAvailable(rowIndex, colIndex) }
50+
onClick={(e) => this.handleSetAvailableTime(rowIndex, colIndex) }
9251
key={colIndex}>
9352
{ (cell.available) ? 'Available' : 'Unavailable' }
9453
</td>
@@ -105,12 +64,50 @@ Timetable.defaultProps = {
10564
days: ['Monday', 'Tuesday', 'Wednesday', 'Thrusday', 'Friday', 'Saturday', 'Sunday'],
10665
start: 10,
10766
end: 18,
108-
diff: 1
67+
diff: 1,
68+
timetable: initTimetable(),
69+
settable: true
10970
}
11071

11172
Timetable.propTypes = {
11273
days: PropTypes.arrayOf(PropTypes.string),
11374
start: PropTypes.number,
11475
end: PropTypes.number,
115-
diff: PropTypes.number
76+
diff: PropTypes.number,
77+
timetable: PropTypes.arrayOf(PropTypes.shape({
78+
cells: PropTypes.arrayOf(PropTypes.shape({ // every day in weeks, e.g. cells[0] = Mon, cells[1] = Tue ...
79+
available: PropTypes.bool // user at this time is available or not
80+
})),
81+
start: PropTypes.number, // start hour
82+
end: PropTypes.number // start hour + diff
83+
})),
84+
settable: PropTypes.bool, // if true, timetable is able to set available time
85+
onSetAvailableTime: PropTypes.func
86+
}
87+
88+
function initTimetable() {
89+
90+
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thrusday', 'Friday', 'Saturday', 'Sunday'],
91+
start = 10,
92+
end = 18,
93+
diff = 1;
94+
95+
let timetable = [];
96+
97+
for (let i = start ; i < end ; i += diff) {
98+
99+
let cells = [];
100+
101+
for (let day in days) {
102+
cells.push({ available: false });
103+
}
104+
105+
timetable.push({
106+
start: i,
107+
end: i + diff,
108+
cells: cells
109+
});
110+
}
111+
112+
return timetable;
116113
}

meetingapp/app/containers/App/App.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ ul.navbar li a:hover {
7373
}
7474

7575
ul.navbar li.logout a {
76-
color: rgb(218, 87, 93);
76+
color: #da575d;
7777
background-color: white;
7878
border-radius: 5px;
7979
margin-right: 20px;
Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,80 @@
11
.container {
2-
3-
}
2+
min-width: 1000px;
3+
}
4+
5+
.infobar {
6+
background-color: white;
7+
margin-bottom: 10px;
8+
border-radius: 5px;
9+
padding: 25px;
10+
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
11+
}
12+
13+
.avatar {
14+
width: 45px;
15+
height: 45px;
16+
vertical-align: middle;
17+
}
18+
19+
.username {
20+
margin-left: 25px;
21+
vertical-align: middle;
22+
color: rgba(0,0,0,0.8);
23+
font-weight: 400;
24+
}
25+
26+
.button {
27+
min-width: 80px;
28+
text-align: center;
29+
float: right;
30+
line-height: 45px;
31+
border-radius: 5px;
32+
padding: 0px 12px 0px 12px;
33+
font-weight: 400;
34+
transition: all 0.3s;
35+
margin-left: 20px;
36+
}
37+
38+
.button:active {
39+
opacity: 0.9;
40+
}
41+
42+
.button.setAvailableTime {
43+
border: 2px solid #50a0ff;
44+
background-color: #edf5ff;
45+
color: #50a0ff;
46+
font-weight: 400;
47+
transition: all 0.3s;
48+
}
49+
50+
.button.setAvailableTime:hover {
51+
background-color: #50a0ff;
52+
color: white;
53+
}
54+
55+
.button.save {
56+
border: 2px solid #00dc73;
57+
background-color: #e5fbf1;
58+
color: #00dc73;
59+
font-weight: 400;
60+
transition: all 0.3s;
61+
}
62+
63+
.button.save:hover {
64+
background-color: #00dc73;
65+
color: white;
66+
}
67+
68+
.button.cancel {
69+
border: 2px solid #da575d;
70+
background-color: #f7ddde;
71+
color: #da575d;
72+
font-weight: 400;
73+
transition: all 0.3s;
74+
}
75+
76+
.button.cancel:hover {
77+
background-color: #da575d;
78+
color: white;
79+
}
80+

meetingapp/app/containers/Home/Home.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { Component, PropTypes } from 'react';
22
import { connect } from 'react-redux';
33
import Timetable from '../../components/Timetable/Timetable';
4+
import * as TimetableActions from '../../actions/timetable';
45
import classnames from 'classnames';
56
import styles from './Home.css';
67

@@ -12,9 +13,25 @@ class Home extends Component {
1213
}
1314

1415
render() {
16+
17+
const { dispatch, auth, timetable } = this.props;
18+
const username = auth.user.get('username');
19+
1520
return(
1621
<div className={styles.container}>
17-
<Timetable />
22+
<div className={styles.infobar}>
23+
<img className={styles.avatar} src={require('../../img/avatar.png')}></img>
24+
<span className={styles.username}>{username}</span>
25+
{
26+
timetable.isSetting
27+
? [
28+
<span key="1" className={classnames(styles.button, styles.cancel)} onClick={() => dispatch(TimetableActions.cancelSetAvailableTime())}>Cancel</span>,
29+
<span key="2" className={classnames(styles.button, styles.save)} onClick={() => dispatch(TimetableActions.cancelSetAvailableTime())}>Save</span>
30+
]
31+
: <span className={classnames(styles.button, styles.setAvailableTime)} onClick={() => dispatch(TimetableActions.requestSetAvailableTime())}>Set available time</span>
32+
}
33+
</div>
34+
<Timetable {...timetable} onSetAvailableTime={(row, col) => dispatch(TimetableActions.setAvailableTime(row, col))} />
1835
</div>
1936
)
2037
}

meetingapp/app/containers/Login/Login.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
.errorMessage {
1111
margin-bottom: 20px;
1212
padding: 12px;
13-
background-color: rgb(243, 197, 195);
14-
color: rgb(218, 87, 93);
13+
background-color: #f7ddde;
14+
color: #da575d;
1515
border-radius: 5px;
1616
}
1717

meetingapp/app/containers/Meeting/Meeting.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Meeting extends Component {
2626
<div className={styles.container}>
2727

2828
<div className={styles.infobar}>
29-
<img className={styles.avatar} src={require('./avatar.png')}></img>
29+
<img className={styles.avatar} src={require('../../img/avatar.png')}></img>
3030
<span className={styles.username}>Howard</span>
3131
<span className={styles.button} onClick={(e) => this.handleToggle()}>Set up a meeting</span>
3232
</div>

meetingapp/app/reducers/auth.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,4 @@ export default function auth(state = initialState, action) {
5757
default:
5858
return state;
5959
}
60-
}
61-
62-
63-
64-
60+
}

meetingapp/app/reducers/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import { combineReducers } from 'redux';
77
import { routeReducer } from 'redux-simple-router';
88
import auth from './auth';
9+
import timetable from './timetable';
910

10-
const reducers = { auth };
11+
const reducers = { auth, timetable };
1112

1213
const rootReducer = combineReducers(Object.assign({}, reducers, {
1314
routing: routeReducer

0 commit comments

Comments
 (0)