bitburner-src/src/StockMarket/ui/StockTickers.tsx

189 lines
6.1 KiB
TypeScript

/**
* React Component for the Stock Market UI. This is the container for all
* of the stock tickers. It also contains the configuration for the
* stock ticker UI (watchlist filter, portfolio vs all mode, etc.)
*/
import * as React from "react";
import { StockTicker } from "./StockTicker";
import { StockTickersConfig, TickerDisplayMode } from "./StockTickersConfig";
import { IStockMarket } from "../IStockMarket";
import { Stock } from "../Stock";
import { OrderTypes } from "../data/OrderTypes";
import { PositionTypes } from "../data/PositionTypes";
import { IPlayer } from "../../PersonObjects/IPlayer";
export type txFn = (stock: Stock, shares: number) => boolean;
export type placeOrderFn = (stock: Stock, shares: number, price: number, ordType: OrderTypes, posType: PositionTypes) => boolean;
type IProps = {
buyStockLong: txFn;
buyStockShort: txFn;
cancelOrder: (params: object) => void;
p: IPlayer;
placeOrder: placeOrderFn;
sellStockLong: txFn;
sellStockShort: txFn;
stockMarket: IStockMarket;
}
type IState = {
rerenderFlag: boolean;
tickerDisplayMode: TickerDisplayMode;
watchlistFilter: string;
watchlistSymbols: string[];
}
export class StockTickers extends React.Component<IProps, IState> {
listRef: React.RefObject<HTMLUListElement>;
constructor(props: IProps) {
super(props);
this.state = {
rerenderFlag: false,
tickerDisplayMode: TickerDisplayMode.AllStocks,
watchlistFilter: "",
watchlistSymbols: [],
}
this.changeDisplayMode = this.changeDisplayMode.bind(this);
this.changeWatchlistFilter = this.changeWatchlistFilter.bind(this);
this.collapseAllTickers = this.collapseAllTickers.bind(this);
this.expandAllTickers = this.expandAllTickers.bind(this);
this.rerender = this.rerender.bind(this);
this.listRef = React.createRef();
}
changeDisplayMode() {
if (this.state.tickerDisplayMode === TickerDisplayMode.AllStocks) {
this.setState({
tickerDisplayMode: TickerDisplayMode.Portfolio,
});
} else {
this.setState({
tickerDisplayMode: TickerDisplayMode.AllStocks,
});
}
}
changeWatchlistFilter(e: React.ChangeEvent<HTMLInputElement>) {
const watchlist = e.target.value;
const sanitizedWatchlist = watchlist.replace(/\s/g, '');
this.setState({
watchlistFilter: watchlist,
});
if (sanitizedWatchlist !== "") {
this.setState({
watchlistSymbols: sanitizedWatchlist.split(","),
});
} else {
this.setState({
watchlistSymbols: [],
});
}
}
collapseAllTickers() {
const ul = this.listRef.current;
if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header");
for (let i = 0; i < tickers.length; ++i) {
const ticker = tickers[i];
if (!(ticker instanceof HTMLButtonElement)) {
continue;
}
if (ticker.classList.contains("active")) {
ticker.click();
}
}
}
expandAllTickers() {
const ul = this.listRef.current;
if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header");
for (let i = 0; i < tickers.length; ++i) {
const ticker = tickers[i];
if (!(ticker instanceof HTMLButtonElement)) {
continue;
}
if (!ticker.classList.contains("active")) {
ticker.click();
}
}
}
rerender() {
this.setState((prevState) => {
return {
rerenderFlag: !prevState.rerenderFlag,
}
});
}
render() {
const tickers: React.ReactElement[] = [];
for (const stockMarketProp in this.props.stockMarket) {
const val = this.props.stockMarket[stockMarketProp];
if (val instanceof Stock) {
// Skip if there's a filter and the stock isnt in that filter
if (this.state.watchlistSymbols.length > 0 && !this.state.watchlistSymbols.includes(val.symbol)) {
continue;
}
let orders = this.props.stockMarket.Orders[val.symbol];
if (orders == null) {
orders = [];
}
// Skip if we're in portfolio mode and the player doesnt own this or have any active orders
if (this.state.tickerDisplayMode === TickerDisplayMode.Portfolio) {
if (val.playerShares === 0 && val.playerShortShares === 0 && orders.length === 0) {
continue;
}
}
tickers.push(
<StockTicker
buyStockLong={this.props.buyStockLong}
buyStockShort={this.props.buyStockShort}
cancelOrder={this.props.cancelOrder}
key={val.symbol}
orders={orders}
p={this.props.p}
placeOrder={this.props.placeOrder}
rerenderAllTickers={this.rerender}
sellStockLong={this.props.sellStockLong}
sellStockShort={this.props.sellStockShort}
stock={val}
/>
)
}
}
return (
<div>
<StockTickersConfig
changeDisplayMode={this.changeDisplayMode}
changeWatchlistFilter={this.changeWatchlistFilter}
collapseAllTickers={this.collapseAllTickers}
expandAllTickers={this.expandAllTickers}
tickerDisplayMode={this.state.tickerDisplayMode}
/>
<ul id="stock-market-list" ref={this.listRef}>
{tickers}
</ul>
</div>
)
}
}