diff --git a/src/Components/StockPicker/StockPicker.css b/src/Components/StockPicker/StockPicker.css new file mode 100644 index 0000000..bfac3d3 --- /dev/null +++ b/src/Components/StockPicker/StockPicker.css @@ -0,0 +1,124 @@ +.stock-picker .title { + position: relative; + font-size: 1em; + color: #FFFFFF; +} + +.stock-picker .title .title-box { + display: inline-block; + padding: 1em 1.25em; + background-color: #00B3D6; + box-shadow: .35em .35em rgba(0, 0, 0, 0.1); +} + +.stock-picker .title .title-tail { + position: absolute; + top: 100%; + left: 0; + width: 1em; + height: 1.5em; + border-top: 1.5em solid #098DAD; + border-left: 1em solid transparent; +} + +.stock-picker .body { + margin-left: 1em; + padding: 1em; +} + +.stock-picker .body .page-description { + float: left; + margin-top: 1em; + color: #00A9D2; +} + +.stock-picker .body .filter { + float: right; + width: 20%; + height: 2.5em; + padding: 0.5em; + padding-left: 1em; + border: 1px solid #000; + color: #00A9D2; +} + +.stock-picker .page-content { + width: 100%; + margin: 1em 0; +} + +.stock-picker .page-content .scrip-box { + width: 20%; + float: left; + margin: 1em 3.33333%; + padding: 1.5em 1em; + box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.20); + border-radius: 0.25em; +} + +.stock-picker .page-content .scrip-box>* { + font-size: 1.5em; +} + +.stock-picker .page-content .scrip-box:nth-child(4n+1) { + margin-left: 0; +} + +.stock-picker .page-content .scrip-box:nth-child(4n) { + margin-right: 0; +} + +.stock-picker .scrip-box .scrip-name { + float: left; +} + +.stock-picker .scrip-box .scrip-details { + float: right; + position: relative; + font-weight: 400; + text-align: right; +} + +.stock-picker .rupee-sign { + font-family: PingFangSC-Light, serif; +} + +.stock-picker .scrip-details .scrip-add { + visibility: hidden; + position: absolute; + right: 0; + top: 0; + width: 1.25em; + height: 1.25em; + border-radius: 50%; + background: #00A9D2; +} + +.stock-picker .scrip-add .scrip-add-text { + position: absolute; + font-size: 1.25em; + color: white; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} + +.stock-picker .scrip-details:hover .scrip-add { + visibility: visible; +} + +.stock-picker .scrip-details:hover .scrip-price { + visibility: hidden; +} + +.stock-picker .page-nav{ + width: 100%; +} + +.stock-picker .page-nav .nav-prev-page { + float: left; +} + +.stock-picker .page-nav .nav-next-page { + float: right; +} \ No newline at end of file diff --git a/src/Components/StockPicker/StockPicker.jsx b/src/Components/StockPicker/StockPicker.jsx new file mode 100644 index 0000000..4f52e2d --- /dev/null +++ b/src/Components/StockPicker/StockPicker.jsx @@ -0,0 +1,185 @@ +/* eslint-disable react/prefer-stateless-function */ +import React, { Component } from 'react'; +import './StockPicker.css'; + +class StockPicker extends Component { + constructor() { + super(); + + // TODO: Make this class variable + this.pageSize = 8; + this.state = { + pageNumber: 1, + }; + } + + componentDidUpdate() { + this.normalizePageNumber(); + } + + getAllowedMinMaxPageNumber() { + const minPageNumber = 1; + const maxPageNumber = Math.ceil(this.getRemainingScripCount() / this.pageSize); + return [minPageNumber, maxPageNumber]; + } + + normalizePageNumber() { + const [minPageNumber, maxPageNumber] = this.getAllowedMinMaxPageNumber(); + + if (this.state.pageNumber < minPageNumber) { + this.setState({ + pageNumber: minPageNumber, + }); + } else if (this.state.pageNumber > maxPageNumber) { + this.setState({ + pageNumber: maxPageNumber, + }); + } + } + + gotoNextPage() { + this.setState((oldState) => { + return { + pageNumber: oldState.pageNumber + 1, + }; + }); + } + + gotoPrevPage() { + this.setState((oldState) => { + return { + pageNumber: oldState.pageNumber - 1, + }; + }); + } + + getRemainingScripCount() { + return Object.keys(this.props.remainingScripPrices).length; + } + + getPageStartEndIndex() { + return [((this.state.pageNumber - 1) * this.pageSize), (this.state.pageNumber * this.pageSize)]; + } + + getCurrentPageScripPrices() { + const pageStartEnd = this.getPageStartEndIndex(); + const filteredScripNames = Object.keys(this.props.remainingScripPrices) + .sort() + .slice(...pageStartEnd); + + const currentPageScripPrices = {}; + filteredScripNames.forEach((scripName) => { + currentPageScripPrices[scripName] = this.props.remainingScripPrices[scripName]; + }); + + return currentPageScripPrices; + } + + static renderTitle() { + return ( +
+
+ PICK STOCKS +
+
+
+ ); + } + + renderScripBoxes() { + const currentPageScripPrices = this.getCurrentPageScripPrices(); + + return ( + + { + Object.keys(currentPageScripPrices).map((scripName) => { + return ( +
{ + ev.dataTransfer.setData('text/plain', scripName); + // eslint-disable-next-line no-param-reassign + ev.dataTransfer.dropEffect = 'copy'; + }} + > +
+ {scripName} +
+
+
+ + {Math.round(currentPageScripPrices[scripName])} +
+ +
+
+
+ ); + }) + } +
+ + ); + } + + renderPageNav() { + const [minPageNumber, maxPageNumber] = this.getAllowedMinMaxPageNumber(); + const isPrevEnabled = (this.state.pageNumber - 1) >= minPageNumber; + const isNextEnabled = (this.state.pageNumber + 1) <= maxPageNumber; + + return ( +
+ + +
+
+ ); + } + + render() { + const countTotal = this.getRemainingScripCount(); + const startEnd = this.getPageStartEndIndex(); + + return ( +
+ {StockPicker.renderTitle()} +
+
+ Showing {startEnd[0]} - {Math.min(startEnd[1], countTotal)} of {countTotal} matching stocks +
+
+ APPLY FILTERS +
+
+
+
+ {this.renderScripBoxes()} +
+ {this.renderPageNav()} +
+
+
+ ); + } +} + +export { StockPicker }; diff --git a/src/Components/StockPicker/index.js b/src/Components/StockPicker/index.js new file mode 100644 index 0000000..13cac5f --- /dev/null +++ b/src/Components/StockPicker/index.js @@ -0,0 +1 @@ +export { StockPicker } from './StockPicker';