mirror of
https://github.com/bendtherules/smallcase-portfolio-builder.git
synced 2026-08-19 00:34:17 +00:00
Added completed stock picker section
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<div className="title">
|
||||||
|
<div className="title-box">
|
||||||
|
PICK STOCKS
|
||||||
|
</div>
|
||||||
|
<div className="title-tail" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderScripBoxes() {
|
||||||
|
const currentPageScripPrices = this.getCurrentPageScripPrices();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
Object.keys(currentPageScripPrices).map((scripName) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="scrip-box"
|
||||||
|
key={scripName}
|
||||||
|
draggable={true}
|
||||||
|
onDragStart={(ev) => {
|
||||||
|
ev.dataTransfer.setData('text/plain', scripName);
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
ev.dataTransfer.dropEffect = 'copy';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="scrip-name">
|
||||||
|
{scripName}
|
||||||
|
</div>
|
||||||
|
<div className="scrip-details">
|
||||||
|
<div className="scrip-price">
|
||||||
|
<span className="rupee-sign">₹ </span>
|
||||||
|
{Math.round(currentPageScripPrices[scripName])}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="scrip-add"
|
||||||
|
onClick={() => { this.props.addScripToPortfolio(scripName); }}
|
||||||
|
>
|
||||||
|
<div className="scrip-add-text">+</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="clearfix" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
<div className="clearfix" />
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPageNav() {
|
||||||
|
const [minPageNumber, maxPageNumber] = this.getAllowedMinMaxPageNumber();
|
||||||
|
const isPrevEnabled = (this.state.pageNumber - 1) >= minPageNumber;
|
||||||
|
const isNextEnabled = (this.state.pageNumber + 1) <= maxPageNumber;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="page-nav">
|
||||||
|
<button
|
||||||
|
className="nav-prev-page"
|
||||||
|
disabled={!isPrevEnabled}
|
||||||
|
onClick={() => { if (isPrevEnabled) { this.gotoPrevPage(); } }}
|
||||||
|
>
|
||||||
|
Prev
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="nav-next-page"
|
||||||
|
disabled={!isNextEnabled}
|
||||||
|
onClick={() => { if (isNextEnabled) { this.gotoNextPage(); } }}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
<div className="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const countTotal = this.getRemainingScripCount();
|
||||||
|
const startEnd = this.getPageStartEndIndex();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="stock-picker">
|
||||||
|
{StockPicker.renderTitle()}
|
||||||
|
<div className="body">
|
||||||
|
<div className="page-description">
|
||||||
|
Showing <b>{startEnd[0]} - {Math.min(startEnd[1], countTotal)}</b> of <b>{countTotal}</b> matching stocks
|
||||||
|
</div>
|
||||||
|
<div className="filter">
|
||||||
|
APPLY FILTERS
|
||||||
|
</div>
|
||||||
|
<div className="clearfix" />
|
||||||
|
<div className="page">
|
||||||
|
<div className="page-content">
|
||||||
|
{this.renderScripBoxes()}
|
||||||
|
</div>
|
||||||
|
{this.renderPageNav()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { StockPicker };
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { StockPicker } from './StockPicker';
|
||||||
Reference in New Issue
Block a user