Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.19",
"@fortawesome/free-solid-svg-icons": "^5.9.0",
"@fortawesome/react-fontawesome": "^0.1.4",
"@material-ui/core": "^4.3.0",
"es6-promise": "^4.2.8",
"font-awesome": "^4.7.0",
"moment": "^2.24.0",
Expand Down
6 changes: 3 additions & 3 deletions src/api/Routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ const history = createBrowserHistory();

class Navigation extends PureComponent {
render() {
const { userEmail } = this.props
const { user } = this.props
return (
<Router history={history}>
<Route exact path="/" component={LoginPage}/>
<AuthorizedRoute isLoggedIn={userEmail} path="/my-meeting" component={MyMeeting} />
<AuthorizedRoute isLoggedIn={user.email} path="/my-meeting" component={MyMeeting} />
</Router>
);
}
}

const mapStateToProps = state => ({
userEmail: state.auth.user.email
user: state.auth.user
})

export default connect(mapStateToProps)(Navigation);
Expand Down
3 changes: 2 additions & 1 deletion src/api/SignIn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export function sendLoginRequest(data) {
if (email === 'test@mail.com' && password === 'test') {
return resolve({
user: {
email: 'test@mail.com'
email: 'test@mail.com',
username: 'Sergey'
}
});
}
Expand Down
10 changes: 10 additions & 0 deletions src/api/tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function createTask(data) {
return new Promise((resolve) => {
const id = Date.now() + Math.random().toString()
return resolve({
taskName: data['New meeting'],
id: id.substr(-5)
});
})
}

13 changes: 13 additions & 0 deletions src/components/Forms/TasksForm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { PureComponent, Fragment } from 'react';
import { Checkbox } from '@material-ui/core';

export class TasksForm extends PureComponent {
render() {
return(
<Fragment>
<Checkbox/>
</Fragment>
)
}
}

68 changes: 68 additions & 0 deletions src/components/Task/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { Fragment, PureComponent } from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import { connect } from 'react-redux';
import { faTrash } from '@fortawesome/free-solid-svg-icons';
import NewTaskForm from '../../scenes/MyMeeting/NewTaskForm'
import { createTaskDescription, deleteTask } from '../../redux/actions/tasks'
import { Wrapper, CheckboxWrapper, CommentForm, Comment, DeleteIcon } from './styles';

class Task extends PureComponent {
state = {
isChecked: false,
isClicked: false
}

get checkboxStatus() {
return this.state.isChecked ? { textDecoration: 'line-through' } : { textDecoration: 'none' }
}

handleCheckboxCheck = () => this.setState({ isChecked: !this.state.isChecked })

handleAddComment = () => this.setState({ isClicked: !this.state.isClicked})

handleCreationComment = data => {
const { onCreateTaskDescription, id } = this.props
onCreateTaskDescription({id, ...data})
this.handleAddComment()
}

handleDeleteTask = () => {
const { onDeleteTask, id } = this.props
onDeleteTask({id})
}

render() {
const { task, id } = this.props
const { isClicked, isChecked } = this.state
return(
<Fragment>
<Wrapper>
<CheckboxWrapper>
<Checkbox onClick={this.handleCheckboxCheck}/>
<p onClick={this.handleAddComment} style={this.checkboxStatus}>{task.taskName}</p>
</CheckboxWrapper>
{!isChecked ? <DeleteIcon onClick={this.handleDeleteTask} icon={faTrash} aria-hidden="true" style={this.disabledButton}/>
: <DeleteIcon icon={faTrash} disabled color/>}
</Wrapper>
<CommentForm>
{ (isClicked && !isChecked) && (
<NewTaskForm name={`task-comment-${id}`} placeholder="Task description" onSubmit={this.handleCreationComment} />
)
}
</CommentForm>
<Comment>
{ task.comment || null }
</Comment>
</Fragment>
)
}
}

const mapDispatchToProps = dispatch => {
return {
onCreateTaskDescription: data => dispatch(createTaskDescription(data)),
onDeleteTask: id => dispatch(deleteTask(id))
}
}

export default connect(null, mapDispatchToProps)(Task)
29 changes: 29 additions & 0 deletions src/components/Task/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import styled from 'styled-components';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

export const Wrapper = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;

export const CheckboxWrapper = styled.div`
display: flex;
align-items: center;
cursor: pointer;
`;

export const CommentForm = styled.div`
margin-left: 50px;
`;

export const Comment = styled.div`
margin: 0 0 10px 42px;
color: grey;
`;

export const DeleteIcon = styled(FontAwesomeIcon)`
cursor: pointer;
pointer-events: ${props => props.disabled ? "none" : "auto"};
color: ${props => props.color ? "grey" : "black"}
`;
14 changes: 14 additions & 0 deletions src/redux/actions/tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { TASK_CREATION_SUCCESS, TASK_DESCRIPTION_CREATION_SUCCESS, TASK_DELETE } from '../constants/tasks';
import { createTask as createTaskRequest } from '../../api/tasks';

export function createTask(data) {
return dispatch => createTaskRequest(data).then(res => dispatch({ type: TASK_CREATION_SUCCESS, payload: res}))
};

export function createTaskDescription(data) {
return dispatch => dispatch({ type: TASK_DESCRIPTION_CREATION_SUCCESS, payload: data})
}

export function deleteTask(id) {
return dispatch => dispatch({ type: TASK_DELETE, payload: id })
}
3 changes: 3 additions & 0 deletions src/redux/constants/tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const TASK_CREATION_SUCCESS = 'TASK_CREATION_SUCCESS';
export const TASK_DESCRIPTION_CREATION_SUCCESS = 'TASK_DESCRIPTION_CREATION_SUCCESS';
export const TASK_DELETE = 'TASK_DELETE';
23 changes: 23 additions & 0 deletions src/redux/reducers/tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TASK_CREATION_SUCCESS, TASK_DESCRIPTION_CREATION_SUCCESS, TASK_DELETE } from '../constants/tasks';

const initialState = []

export default function task(state = initialState, action) {
switch (action.type) {
case TASK_CREATION_SUCCESS:
return [ ...state, { ...action.payload, comment: '' } ];
case TASK_DESCRIPTION_CREATION_SUCCESS:
return buildTasks(state, action.payload)
case TASK_DELETE:
return state.filter(item => item.id != action.payload.id)
default:
return state;
}
}

function buildTasks(state, payload) {
const findTaskById = () => state.find(task => task.id === payload['id'])
const taskPosition = state.indexOf(findTaskById())
state[taskPosition].comment = payload[`task-comment-${payload.id}`]
return state
}
2 changes: 2 additions & 0 deletions src/redux/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { reducer as formReducer } from 'redux-form';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import auth from './reducers/auth';
import tasks from './reducers/tasks'

const rootReducer = combineReducers({
auth,
tasks,
form: formReducer
})

Expand Down
46 changes: 46 additions & 0 deletions src/scenes/MyMeeting/NewTaskForm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { PureComponent } from 'react';
import { Field, reduxForm } from 'redux-form'
import { compose } from 'redux';
import { connect } from 'react-redux'
import Input from '@material-ui/core/Input';

const renderTextField = ({
input,
label,
meta: { touched, error },
...custom
}) => (
<Input
hintText={label}
floatingLabelText={label}
errorText={touched && error}
{...input}
{...custom}
/>
)

class NewTaskForm extends PureComponent{
handleFormSubmit = (data) => {
this.props.handleSubmit(data)
this.props.reset()
}
render() {
const { placeholder, name } = this.props
return(
<form onSubmit={this.handleFormSubmit}>
<Field component={renderTextField} placeholder={placeholder} name={name} />
</form>
)
}
}

const mapStateToProps = (state, ownProps) => {
return {
form: ownProps.name
}
}

export default compose(
connect(mapStateToProps),
reduxForm({})
)(NewTaskForm);
33 changes: 23 additions & 10 deletions src/scenes/MyMeeting/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { connect } from 'react-redux';
import { logout } from '../../redux/actions/auth';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import moment from 'moment';
import NewTaskForm from './NewTaskForm';
import { createTask } from '../../redux/actions/tasks'
import Task from '../../components/Task';
import "react-datepicker/dist/react-datepicker.css";
import { CalendarContainer, Header, HeaderContainer, HeaderAction, DatePicker, Body, Logo, Img, HeaderLabel, TasksList, ActionButton } from './styles'
import { CalendarContainer, Header, HeaderContainer, HeaderAction, DatePicker, Body, Logo, Img, HeaderLabel, TasksList, ActionButton, Kek } from './styles'
class MyMeeting extends PureComponent {

state = {
Expand All @@ -26,7 +29,10 @@ class MyMeeting extends PureComponent {

handleChange = date => this.setState({day: date})

handleNewTaskCreation = data => this.props.onCreateTask(data)

render() {
const { tasks, user } = this.props
return (
<Fragment>
<Header>
Expand All @@ -37,7 +43,7 @@ class MyMeeting extends PureComponent {
</HeaderLabel>
</Logo>
<HeaderContainer>
<p>Hi, Test</p>
<p>Hi, {user.username}</p>
<HeaderAction icon={faTimes} aria-hidden="true" onClick={this.handleSignOut}/>
</HeaderContainer>
</Header>
Expand All @@ -48,23 +54,30 @@ class MyMeeting extends PureComponent {
</CalendarContainer>
<hr/>
<TasksList>
<span>задача </span>
<span>delete icon</span>
<br/>
<input></input>
<br/>
<ActionButton>Complete meeting</ActionButton>
{ tasks && tasks.map(task => <Task key={task.id} task={task} id={task.id} />)}
<NewTaskForm name="New meeting" placeholder="New task..." onSubmit={this.handleNewTaskCreation} />
</TasksList>
<Kek>
<ActionButton>Complete meeting</ActionButton>
</Kek>
</Body>
</Fragment>
);
}
}

const mapStateToProps = state => {
return {
tasks: state.tasks,
user: state.auth.user
}
}

const mapDispatchToProps = dispatch => {
return {
logoutAction: () => dispatch(logout())
logoutAction: () => dispatch(logout()),
onCreateTask: data => dispatch(createTask(data)),
}
}

export default connect(null, mapDispatchToProps)(MyMeeting);
export default connect(mapStateToProps, mapDispatchToProps)(MyMeeting);
5 changes: 5 additions & 0 deletions src/scenes/MyMeeting/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,8 @@ export const ActionButton = styled.button`
background-color: white;
}
`;

export const Kek = styled.div`
display: flex;
justify-content: flex-end;
`;
Loading