From 2896b39b9075db655a0774068bb1bcc7f4fab310 Mon Sep 17 00:00:00 2001
From: Bereczki Sandor <bsandor453@gmail.com>
Date: Sun, 20 Jan 2019 02:13:28 +0100
Subject: [PATCH] Homeworks page - task list

Listing the tasks based by its properties and states, also counting with empty lists.
---
 src/actions/homework.js          |  30 +++
 src/actions/types.js             |   3 +
 src/components/Header.js         |   5 +
 src/components/Main.js           |  40 ++--
 src/components/pages/Homework.js | 329 ++++++++++++++++++-------------
 src/reducers/HomeworksReducer.js |  18 ++
 src/reducers/index.js            |   2 +
 7 files changed, 270 insertions(+), 157 deletions(-)
 create mode 100644 src/actions/homework.js
 create mode 100644 src/reducers/HomeworksReducer.js

diff --git a/src/actions/homework.js b/src/actions/homework.js
new file mode 100644
index 0000000..a35110e
--- /dev/null
+++ b/src/actions/homework.js
@@ -0,0 +1,30 @@
+import { axios } from './auth';
+import { GET_HOMEWORKS, GET_SOLUTIONS } from './types';
+
+export const getHomeworks = () => (
+  async (dispatch) => {
+    try {
+      const response = await axios.get('/api/v1/homework/tasks/');
+      dispatch({
+        type: GET_HOMEWORKS,
+        payload: response.data,
+      });
+    } catch (e) {
+      console.log(e);
+    }
+  }
+);
+
+export const getSolutions = () => (
+  async (dispatch) => {
+    try {
+      const response = await axios.get('/api/v1/homework/solutions/');
+      dispatch({
+        type: GET_SOLUTIONS,
+        payload: response.data,
+      });
+    } catch (e) {
+      console.log(e);
+    }
+  }
+);
diff --git a/src/actions/types.js b/src/actions/types.js
index 177bbd7..0fa7e52 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -10,3 +10,6 @@ export const ADD_NEWS = 'add_news';
 export const DELETE_NEWS = 'delete_news';
 export const EDIT_NEWS = 'edit_news';
 export const SELECT_NEWS = 'select_news';
+
+export const GET_HOMEWORKS = 'get_homeworks';
+export const GET_SOLUTIONS = 'get_solutions';
diff --git a/src/components/Header.js b/src/components/Header.js
index e0a9d17..4ea3c7d 100644
--- a/src/components/Header.js
+++ b/src/components/Header.js
@@ -34,6 +34,11 @@ const menuItems = [
     to: '/schedule',
     prefix: '',
   },
+  {
+    text: 'HĂĄzi feladatok',
+    to: '/homework',
+    prefix: '',
+  },
 ]
 
 const FixedMenu = ({ user }) => (
diff --git a/src/components/Main.js b/src/components/Main.js
index c24e23e..8307cbb 100644
--- a/src/components/Main.js
+++ b/src/components/Main.js
@@ -1,27 +1,27 @@
-import React from 'react';
-import { Switch, Route, Redirect, withRouter } from 'react-router-dom';
+import React from "react";
+import { Switch, Route, Redirect, withRouter } from "react-router-dom";
 
-import Home from './pages/Home';
-import Trainers from './pages/Trainers';
-import Schedule from './pages/Schedule';
-import NotFound from './pages/NotFound';
-import Profile from './pages/Profile';
-import Statistics from './pages/Statistics';
-import Groups from './pages/Groups';
-import News from './pages/News';
-import Homework from './pages/Homework';
+import Home from "./pages/Home";
+import Trainers from "./pages/Trainers";
+import Schedule from "./pages/Schedule";
+import NotFound from "./pages/NotFound";
+import Profile from "./pages/Profile";
+import Statistics from "./pages/Statistics";
+import Groups from "./pages/Groups";
+import News from "./pages/News";
+import Homework from "./pages/Homework";
 
 const Main = () => (
   <Switch>
-    <Redirect exact from='/' to='/home' />
-    <Route exact path='/home' component={Home} />
-    <Route path='/news' component={News} />
-    <Route path='/trainers' component={Trainers} />
-    <Route path='/schedule' component={Schedule} />
-    <Route path='/profile' component={withRouter(Profile)} />
-    <Route path='/statistics' component={Statistics} />
-    <Route path='/groups' component={Groups} />
-    <Route path='/homework' component={Homework} />
+    <Redirect exact from="/" to="/home" />
+    <Route exact path="/home" component={Home} />
+    <Route path="/news" component={News} />
+    <Route path="/trainers" component={Trainers} />
+    <Route path="/schedule" component={Schedule} />
+    <Route path="/profile" component={withRouter(Profile)} />
+    <Route path="/statistics" component={Statistics} />
+    <Route path="/groups" component={Groups} />
+    <Route path="/homework" component={Homework} />
     <Route component={NotFound} />
   </Switch>
 );
diff --git a/src/components/pages/Homework.js b/src/components/pages/Homework.js
index ae6a7bf..94aa758 100644
--- a/src/components/pages/Homework.js
+++ b/src/components/pages/Homework.js
@@ -1,150 +1,205 @@
-import React, { Component } from "react";
+import React, { Component } from 'react';
 import {
   Container,
   Header,
   Segment,
-  Grid,
-  Image,
   Table,
-  Icon
-} from "semantic-ui-react";
+  Icon,
+  Message,
+} from 'semantic-ui-react';
+import { connect } from 'react-redux';
+import moment from 'moment';
+import { getHomeworks, getSolutions } from '../../actions/homework';
+
+const displayTypes = {
+  can_submit: {
+    text: 'BeadhatĂł',
+    icon: 'send',
+    rowstyle: { warning: false, positive: false, negative: false },
+  },
+  no_submit: {
+    text: 'BeadĂĄs elmaradt',
+    icon: 'warning circle',
+    rowstyle: { warning: true, positive: false, negative: false },
+  },
+  wait_correction: {
+    text: 'JavĂ­tĂĄsra vĂĄr',
+    icon: 'wait',
+    rowstyle: { warning: true, positive: false, negative: false },
+  },
+  no_accept: {
+    text: 'Nem elfogadhatĂł',
+    icon: 'warning circle',
+    rowstyle: { warning: false, positive: false, negative: true },
+  },
+  accepted: {
+    text: 'Elfogadva',
+    icon: 'checkmark',
+    rowstyle: { warning: false, positive: true, negative: false },
+  },
+};
+
+const emptyMessage = (header, text, marginBottom) => (
+  <Message
+    style={{ marginBottom }}
+    icon='info'
+    info
+    header={header}
+    content={text}
+  />
+);
+
+class Homework extends Component {
+  componentDidMount() {
+    this.props.getHomeworks();
+    this.props.getSolutions();
+  }
+
+  getTaskDisplayStyle(task) {
+    const taskSolutions = this.props.homeworks.solutions.filter(solution =>
+      solution.task === task.id);
+
+    if (taskSolutions.length === 0) {
+      if (this.isTaskActive(task)) {
+        return 'can_submit';
+      }
+
+      return 'no_submit';
+    }
+
+    if (taskSolutions[taskSolutions.length - 1].corrected === false) {
+      return 'wait_correction';
+    }
+
+    if (taskSolutions[taskSolutions.length - 1].accepted === false) {
+      return 'no_accept';
+    }
+
+    return 'accepted';
+  }
+
+  isTaskActive(task) {
+    return moment().isBefore(task.deadline);
+  }
+
+  renderTaskList(active) {
+    return this.props.homeworks.tasks
+      .filter(task => moment().isBefore(task.deadline) === active)
+      .map(task => (
+        <Table.Row
+          key={task.id}
+          warning={
+            displayTypes[this.getTaskDisplayStyle(task)].rowstyle.warning
+          }
+          positive={
+            displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive
+          }
+          negative={
+            displayTypes[this.getTaskDisplayStyle(task)].rowstyle.negative
+          }
+        >
+          <Table.Cell>
+            {task.title} <Icon name='external' />
+          </Table.Cell>
+          <Table.Cell>
+            {moment(task.deadline).format('YYYY. MM. DD. hh:mm')}{' '}
+            {this.props.homeworks.id}
+          </Table.Cell>
+          <Table.Cell>
+            <Icon name={displayTypes[this.getTaskDisplayStyle(task)].icon} />{' '}
+            {displayTypes[this.getTaskDisplayStyle(task)].text}
+          </Table.Cell>
+        </Table.Row>
+      ));
+  }
+
+  renderHomeworksTable(active) {
+    let tableColor = 'green';
+    let marginBottom = '0em';
+
+    if (!active) {
+      tableColor = 'blue';
+      marginBottom = '3em';
+    }
+
+    return (
+      <Table color={tableColor} fixed style={{ marginBottom }}>
+        <Table.Header>
+          <Table.Row>
+            <Table.HeaderCell>
+              <Icon circular name='home' />
+              Feladat megnevezĂŠse
+            </Table.HeaderCell>
+            <Table.HeaderCell>
+              <Icon circular name='calendar' />
+              Beadási határidő
+            </Table.HeaderCell>
+            <Table.HeaderCell>
+              <Icon circular name='tasks' />
+              Állapot
+            </Table.HeaderCell>
+          </Table.Row>
+        </Table.Header>
+        <Table.Body>{this.renderTaskList(active)}</Table.Body>
+      </Table>
+    );
+  }
+
+  renderHomeworks(active) {
+    let empty = false;
+    let emptyText = 'Jelenleg nincs egyetlen beadhatĂł feladat sem. ';
+    let marginBottom = '0em';
+    const emptyHeaderText = 'Nincs feladat.';
+    let headerText = 'AktĂ­v feladatok';
+
+    if (
+      this.props.homeworks.tasks.filter(task =>
+        moment().isBefore(task.deadline) === active).length === 0
+    ) {
+      empty = true;
+    }
+
+    if (!active) {
+      headerText = 'LejĂĄrt hatĂĄridejĹą feladatok';
+      emptyText = 'Jelenleg nincs egyetlen lejĂĄrt hatĂĄridejĹą feladat sem.';
+      marginBottom = '3em';
+    }
+
+    return (
+      <Segment style={{ padding: '0 0 2em 0' }} vertical basic>
+        <Container>
+          <Header
+            as='h1'
+            dividing
+            content={headerText}
+            style={{
+              fontSize: '3em',
+              fontWeight: 'normal',
+              marginBottom: 0,
+              marginTop: '0.5em',
+            }}
+          />
+          {empty
+            ? emptyMessage(emptyHeaderText, emptyText, marginBottom)
+            : this.renderHomeworksTable(active)}
+        </Container>
+      </Segment>
+    );
+  }
 
-export default class Homework extends Component {
   render() {
     return (
       <div>
-        <Segment inverted textAlign="center" vertical>
-          <Container>
-            <Header
-              as="h1"
-              content="HĂĄzi feladatok"
-              inverted
-              style={{
-                fontSize: "3em",
-                fontWeight: "normal",
-                marginBottom: 0,
-                marginTop: "0.5em"
-              }}
-            />
-          </Container>
-        </Segment>
-        <Segment vertical>
-          <Container>
-            <Header
-              as="h1"
-              dividing
-              content="AktĂ­v feladatok"
-              style={{
-                fontSize: "3em",
-                fontWeight: "normal",
-                marginBottom: 0,
-                marginTop: "0.5em"
-              }}
-            />
-            <Table color="green">
-              <Table.Header>
-                <Table.Row>
-                  <Table.HeaderCell>
-                    <Icon circular name="home" />Feladat megnevezĂŠse
-                  </Table.HeaderCell>
-                  <Table.HeaderCell>
-                    <Icon circular name="calendar" />Beadási határidő
-                  </Table.HeaderCell>
-                  <Table.HeaderCell>
-                    <Icon circular name="tasks" />Állapot
-                  </Table.HeaderCell>
-                </Table.Row>
-              </Table.Header>
-
-              <Table.Body>
-                <Table.Row>
-                  <Table.Cell>
-                    Protocols <Icon name="external" />
-                  </Table.Cell>
-                  <Table.Cell>2018. 03. 05. 23:59</Table.Cell>
-                  <Table.Cell>
-                    <Icon name="send" />BeadhatĂł
-                  </Table.Cell>
-                </Table.Row>
-                <Table.Row warning>
-                  <Table.Cell>
-                    Networks <Icon name="external" />
-                  </Table.Cell>
-                  <Table.Cell>2018. 03. 01. 23:59</Table.Cell>
-                  <Table.Cell>
-                    <Icon name="wait" />JavĂ­tĂĄsra vĂĄr
-                  </Table.Cell>
-                </Table.Row>
-                <Table.Row negative>
-                  <Table.Cell>
-                    Security <Icon name="external" />
-                  </Table.Cell>
-                  <Table.Cell>2018. 02. 28. 23:59</Table.Cell>
-                  <Table.Cell>
-                    <Icon name="warning circle" />Nem elfogadhatĂł
-                  </Table.Cell>
-                </Table.Row>
-              </Table.Body>
-            </Table>
-            <Header
-              as="h1"
-              dividing
-              content="LejĂĄrt hatĂĄridejĹą feladatok"
-              style={{
-                fontSize: "3em",
-                fontWeight: "normal",
-                marginBottom: 0,
-                marginTop: "2em"
-              }}
-            />
-            <Table color="blue">
-              <Table.Header>
-                <Table.Row>
-                  <Table.HeaderCell>
-                    <Icon circular name="home" />Feladat megnevezĂŠse
-                  </Table.HeaderCell>
-                  <Table.HeaderCell>
-                    <Icon circular name="calendar" />Beadási határidő
-                  </Table.HeaderCell>
-                  <Table.HeaderCell>
-                    <Icon circular name="tasks" />Állapot
-                  </Table.HeaderCell>
-                </Table.Row>
-              </Table.Header>
-
-              <Table.Body>
-                <Table.Row warning>
-                  <Table.Cell>
-                    BASH <Icon name="external" />
-                  </Table.Cell>
-                  <Table.Cell>2018. 02. 30. 23:59</Table.Cell>
-                  <Table.Cell>
-                    <Icon name="warning circle" />BeadĂĄs elmaradt
-                  </Table.Cell>
-                </Table.Row>
-                <Table.Row positive>
-                  <Table.Cell>
-                    Virtualbox <Icon name="external" />
-                  </Table.Cell>
-                  <Table.Cell>2018. 02. 25. 23:59</Table.Cell>
-                  <Table.Cell>
-                    <Icon name="checkmark" />Elfogadva
-                  </Table.Cell>
-                </Table.Row>
-                <Table.Row positive>
-                  <Table.Cell>
-                    Selfie <Icon name="external" />
-                  </Table.Cell>
-                  <Table.Cell>2018. 02. 20. 23:59</Table.Cell>
-                  <Table.Cell>
-                    <Icon name="checkmark" />Elfogadva
-                  </Table.Cell>
-                </Table.Row>
-              </Table.Body>
-            </Table>
-          </Container>
-        </Segment>
+        {this.renderHomeworks(true)}
+        {this.renderHomeworks(false)}
       </div>
     );
   }
 }
+
+const mapStateToProps = ({ homeworks, user }) => ({ homeworks, user });
+
+export default connect(
+  mapStateToProps,
+  { getHomeworks, getSolutions },
+)(Homework);
diff --git a/src/reducers/HomeworksReducer.js b/src/reducers/HomeworksReducer.js
new file mode 100644
index 0000000..87e09ee
--- /dev/null
+++ b/src/reducers/HomeworksReducer.js
@@ -0,0 +1,18 @@
+import { GET_HOMEWORKS, GET_SOLUTIONS } from '../actions/types';
+
+const INITIAL_STATE = {
+  tasks: [],
+  solutions: [],
+};
+
+
+export default (state = INITIAL_STATE, action) => {
+  switch (action.type) {
+    case GET_HOMEWORKS:
+      return { ...state, tasks: action.payload };
+    case GET_SOLUTIONS:
+      return { ...state, solutions: action.payload };
+    default:
+      return state;
+  }
+};
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 370c0af..71adb52 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -3,12 +3,14 @@ import UserReducer from './UserReducer';
 import NewsReducer from './NewsReducer';
 import AddNewsReducer from './AddNewsReducer';
 import EditNewsReducer from './EditNewsReducer';
+import HomeworksReducer from './HomeworksReducer';
 
 const rootReducer = combineReducers({
   user: UserReducer,
   news: NewsReducer,
   newNews: AddNewsReducer,
   selectedNews: EditNewsReducer,
+  homeworks: HomeworksReducer,
 });
 
 export default rootReducer;
-- 
GitLab