Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SideDrawer.js 12.53 KiB
import React from "react";
import ToggleButton from "./ToggleButton";
import CitySelector from "./CitySelector";
import SwitchButtons from "./SwitchButtons";
import LinesStopsBtn from "./LinesStopsBtn";
import Delays from "./Delays";
import HistoryBox from "../HistoryBox/HistoryBox";
import StopDisplay from "../StopDisplay/StopDisplay.js";

import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import Drawer from "@material-ui/core/Drawer";
import { IconButton} from "@material-ui/core";
import Divider from "@material-ui/core/Divider";
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
import Toolbar from "@material-ui/core/Toolbar";

import LinkLines from "../../Data/LinkLines";
import LinkStops from "../../Data/LinkStops";
import NorrLines from "../../Data/NorrLines";
import NorrStops from "../../Data/NorrStops";

import styles from "./SideDrawerCSS.js";

// This is what gets returned from back-end after getProbOfLine(), only used as an example
//{smallestP: "10%"},
const rydsCentrumLine1 = [
  { expectedTime: "07:05", arrivalP: "80%" },
  { expectedTime: "07:20", arrivalP: "10%" },
  { expectedTime: "07:35", arrivalP: "75%" },
  { expectedTime: "07:50", arrivalP: "35%" }
];

//rydsCentrumLine1[0].smallestP
const rydsCentrum = [
  { lineName: "1", smallestP: "10%", lineDetails: rydsCentrumLine1 },
  { lineName: "4", smallestP: "20%", lineDetails: rydsCentrumLine1 },
  { lineName: "2", smallestP: "35%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 },
  { lineName: "3", smallestP: "56%", lineDetails: rydsCentrumLine1 }
];

class sideDrawer extends React.PureComponent {
  constructor(props) {
    super(props);
    this.removeLine = this.removeLine.bind(this);
    this.updateStopToDisplay = this.updateStopToDisplay.bind(this);
    this.state = {
      menuOn: false,
      trafficFlow: false,
      lines: false,
      stop: false,
      linkoping: false,
      norrkoping: false,
      city: "",
      linesList: [],
      stopsList: [],
      savedLines: [],
      showHistory: false,
      stopToDisplay: "",
      citySelector: false,
      delays: [],
      delaysFilter: {day: "", time: [7,8], percent: 50},
    };
  }

  /*
   * Toggles state of the side bar
   * @param {string} side Name of the selected variable  
   * @param {bool} open State to be updated   
   */
  toggleDrawer = (side, open) => () => {
    this.setState({
      [side]: open
    });
  };

  /*
   * Calls removeLine() or addLine() based on the event on the checkBox   
   * @param {event} event Triggered event with its props   
   * @param {num} id Selected line number
   */
  checkBoxHandler = (event) => {
    let line = event.target.id
    if (this.state.savedLines.includes(line)) {
      this.removeLine(line)
    } else {
      this.addLine(line)
    }
  };

  /*
   * Updates savedLines list by adding the selected (from sideDrawer) line
   * @param {num} line selected line to be added
   */
  addLine = (line)  => {
    this.setState({
      savedLines: [...this.state.savedLines, line],
      showHistory: true
    });
  };

  /*
   * Updates savedLines by removing the selected (from sideDrawe or historyBox) line
   * @param {num} line Selected line to be removed    
   */
  removeLine = (line) => {
    var sh = true;
    var savedLinesCopy = [...this.state.savedLines];
    var index = savedLinesCopy.indexOf(line);

    if (index > -1) {
      savedLinesCopy.splice(index, 1);
    }
    if (savedLinesCopy.length == 0) {
      sh = false;
    }
    this.setState({
      savedLines: savedLinesCopy,
      showHistory: sh
    });
  }

  /*
   * @param { } stop   
   */
  updateStopToDisplay(stop) {
    this.setState({
      stopToDisplay: stop
    });
  }

  /*
   * 
   */
  showHistory = () => {
    this.setState({
      showHistory: true
    });
  };

  /*
   * Updates city state which contains the name of the selected city 
   * Updates lines and stops lists according selected city
   * @param {event} event The triggered event with its props  
   * @param {string} value Name of the selected city
   */
  cityChoiceHandler = event => {
    if (event.target.value !== "") {
      this.setState({
        city: event.target.value,
        linesList: this.updateLinesList(event.target.value),
        stopsList: this.updateStopsList(event.target.value)
      });
    } else {
      this.setState({
        city: event.target.value
      });
    }
  };

  /*
   * Returns the state of the switched button
   * @param {string} name State name of the switched button  
   * @return {bool} State of the switched button   
   */
  getSwitchedBtn = name => {
    switch (name) {
      case "trafficFlow":
        return this.state.trafficFlow;

      default:
        return;
    }
  };

  /*
   * Updates state of the switched button
   * @param {string} name State name of the switched button
   * @param {event} event The triggered event with its props 
   * @param {bool} checked Button new state
   */
  toggleSwitchedBtn = name => event => {
    this.setState({
      [name]: event.target.checked
    });
  };

  /*
    Update selected item.
    Item chosen from lines or stops list
  */
  updateSelectedItem = event => {
    this.setState({
      selectedItem: event.target.value
    });
  };

  /*
    Temporarily used as Linköping/Norrköping's
    bus lines data.
    Updates the lines list based on the city selection.
  */
  updateLinesList = city => {
    switch (city) {
      case "Linköping":
        return LinkLines;

      case "Norrköping":
        return NorrLines;

      default:
        return;
    }
  };

  /*
    Temporarily used as Linköping/Norrköping's
    bus stops data.
    Updates the stops list based on the city selection.
  */
  updateStopsList = city => {
    switch (city) {
      case "Linköping":
        return LinkStops;

      case "Norrköping":
        return NorrStops;

      default:
        return;
    }
  };

  /*
   * Updates the state of the given delays filter variable
   * @param {string} filter Name of the variable to be updated  
   * @param {string, array, num} input New value of the selected filter var   
   */
  delaysFilterHandler = (filter, input) => {
    switch(filter) {
      case "day":
        this.setState(prevState => ({
          delaysFilter: {
              ...prevState.delaysFilter,
              day: input
          }
        }));
        break;
      case "time":
        this.setState(prevState => ({
          delaysFilter: {
            ...prevState.delaysFilter,
            time: input
          }
        }));
        break;
      case "percent":
        this.setState(prevState => ({
          delaysFilter: {
            ...prevState.delaysFilter,
            percent: input
          }
        }));
        break;
    }
  }  

  /*
   * Updates the start value of time interval on delays filter
   * according to selected tim value
   * @param {num} input Selected start time value     
   */
  updateStartInterval = input => {
    let value = parseInt(input, 10);
    let end = this.state.delaysFilter.time[1]
    if (value > 23) {
      return [1, end];
    } else if (value < 1) {
      return [23, end];
    } else if (end <= value) {
      return [value, value+1];
    } else {
      return [value, end];
    }
  };

  /*
   * Updates the end value of time interval on delays filter
   * according to selected time value
   * @param {num} input Selected end time value     
   */
  updateEndInterval = input => {
    let value = parseInt(input, 10)
    let start = this.state.delaysFilter.time[0]
    if (value <= start) {
      return [start, start+1];
    } else if (value > 24) {
      return [start, 24];
    } else if (value < 1) {
      return [start, 1];
    } else {
      return [start, value]
    }
  };

  /*
   * Handles the triggered time point (start or end)
   * Calls respective function to update selected time point
   * Calls respective function to update selected time point state/value
   * @param {event} event Triggered event with its props
   * @param {string} id Name of the triggered time point     
   */
  intervalHandler = event => {
    let interval = []
    switch (event.target.id) {
      case "start":
        interval = this.updateStartInterval(event.target.value)
        this.delaysFilterHandler("time", interval)
        break;
      case "end":
        interval = this.updateEndInterval(event.target.value)
        this.delaysFilterHandler("time", interval)
        break;
      default:
        return;
    }
  };

   /*
   * Calls respective function to update percent on delays filter
   * @param {event} event Triggered event with its props
   * @param {num} value New selected percent on delays filter     
   */
  filterSliderHandler = (event, value) => {
    let percent = Math.round(value);
    this.delaysFilterHandler("percent", percent)
  };

  /* This is sent to backend which returns a complete list which is 
  * in the form of the "rydsCentrum" constant
  */
  getProbOfStop = (stop, linte, day, startTime, endTime) => {
    return rydsCentrum;
  };

  /*This is sent to back-end which returns a tuple? of the the different 
  * times a bus is scheduled to arrive and
  * their respective percentage of arriving at that time. Alternativly we 
  * can get this whole list only once but I think this is a performance/preference question
  */
  getProbOfLine = (stop, line, day, startTime, endTime) => {
    return rydsCentrumLine1;
  };

  render() {
    const { classes } = this.props;

    const sideBar = (
     <div className={classes.menu}>
        <div className={classes.arrowContainer}>
          <IconButton onClick={this.toggleDrawer("menuOn", !this.state.menuOn)}>
            <ChevronLeftIcon className={classes.arrow} />
          </IconButton>
        </div>
        <Divider />

        <CitySelector
          city={this.state.city}
          cityChoiceHandler={this.cityChoiceHandler}
        />
        <SwitchButtons
          switchedBtn={this.getSwitchedBtn}
          toggleBtn={this.toggleSwitchedBtn}
        />

        {this.state.city !== "" ? (
          <div className={classes.expansionContainer}>
            <LinesStopsBtn
              linesList={this.state.linesList}
              stopsList={this.state.stopsList}
              ckeckBoxHandler={this.checkBoxHandler}
              savedLines={this.state.savedLines}
              addLine={this.addLine}
              removeLine={this.removeLine}
              updateStopToDisplay={this.updateStopToDisplay}
            /> 

            <Delays
              delaysFilterHandler={this.delaysFilterHandler}
              delaysFilter={this.state.delaysFilter}
              intervalHandler={this.intervalHandler}
              intervalValue={this.getIntervalValue}
              sliderHandler={this.filterSliderHandler}
            />
          </div>
        ) : null}
      </div>
    );

    return (
      <div>
        <Toolbar style={{position: 'absolute'}}>
          <ToggleButton toggleDrawer={this.toggleDrawer} />
        </Toolbar>

        <Drawer
          classes={{
            paper: classes.sideDrawer
          }}
          open={this.state.menuOn}
          onClose={this.toggleDrawer("menuOn", false)}
        >
          {sideBar}
        </Drawer>

        {this.state.showHistory ? (
          <HistoryBox
            removeLine={this.removeLine}
            savedLines={this.state.savedLines}
          />
        ) : null}

        {/* Get the lines that connect to a specific stop 
        and their percentages of arriving on time*/}
        {this.state.stopToDisplay != "" ? (
          <StopDisplay
            stop={this.state.stopToDisplay}
            closeDisplay={this.updateStopToDisplay}
            linesList={this.state.linesList}
            connectedLines={
              rydsCentrum /*this.getProbOfStop(this.state.stopToDisplay)*/
            }
          />
        ) : null}
      </div>
    );
  }
}

sideDrawer.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(sideDrawer);