Skip to content

Commit

Permalink
Merge pull request #10 from alecsloan/dev
Browse files Browse the repository at this point in the history
v1.1.0
  • Loading branch information
alecsloan authored Mar 13, 2021
2 parents 6f920e6 + 412b758 commit b2bc411
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 135 deletions.
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,14 @@ Just run `npm start`
![Mobile Image](https://imgur.com/HxhUnR5.png)

# Todo
* Add a light theme
* Add full configuration for color picking so users can set their own colors/gradients
* Add setting for sorting cards (Market Cap, holdings, price, etc)
* Add multi-language support
* Get list of tokens dynamically, using a static list of tokens is limiting
* Add functionality for interest bearing assets
* Add functionality for exit strategy planning

v1.1.0 Planning:
* Add timestamp for last time data was updated
* Make it more clear that prices and value changes were updated (maybe similar to what CMC does?)
* Add link to CMC/CG page if someone clicks on the asset name/symbol
* Add configuration for hiding CryptoDash title
* Add Skeleton for cards while loading
* Add Skeleton for cards while loading
* Add different layout views (table, main portfolio change chart with small cards, etc.)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cryptodash",
"version": "1.0.3",
"version": "1.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "latest",
Expand Down
125 changes: 81 additions & 44 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,45 @@
import Card from './Components/Card.js';
import AssetCard from './Components/AssetCard.js';
import Header from './Components/Header.js';
import Hotkeys from 'react-hot-keys';
import React, { Component } from 'react';
import Settings from './Components/Settings.js';

import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';

import './styles/App.css';
import {IconButton, Snackbar} from "@material-ui/core";
import {colors, CssBaseline, IconButton, Snackbar} from "@material-ui/core";
import CloseIcon from '@material-ui/icons/Close';

const CORS_PROXY = 'https://cors.bridged.cc/'

const darkTheme = createMuiTheme({
palette: {
type: "dark",
background: {
default: "#1c2025",
paper: colors.grey[800]
},
primary: {
main: colors.grey[900]
}
}
});

const lightTheme = createMuiTheme({
palette: {
type: "light"
}
});

function CardRow(props) {
var cards = [];

if (!props.assets)
return <div></div>;

props.assets.forEach(asset => {
cards.push(<Card asset={asset} key={asset.symbol} removeCrypto={props.removeCrypto.bind(this)} settings={props.settings} updateHoldings={props.updateHoldings.bind(this)}/>)
cards.push(<AssetCard asset={asset} key={asset.symbol} removeCrypto={props.removeCrypto.bind(this)} settings={props.settings} updateHoldings={props.updateHoldings.bind(this)}/>)
});

return <div className="cardRow">{cards}</div>;
Expand All @@ -37,15 +59,18 @@ class App extends Component {
decimals3: 1,
decimals4: null,
fetchInterval: 300000,
limit: 200,
limit: 5000,
show1hChange: true,
show24hChange: true,
show7dChange: true,
showCardBalances: true,
showPortfolioBalance: true,
sliderMax: 10000
sliderMax: 10000,
theme: lightTheme
};

initialSettings.theme = createMuiTheme(initialSettings.theme);

this.state ={
cards: [],
cryptoassets: require("./cryptoassets.json").slice(0, initialSettings.limit),
Expand Down Expand Up @@ -100,17 +125,27 @@ class App extends Component {
cryptoassets: require("./cryptoassets.json").slice(0, value)
});
}
else if (settingName === "theme") {
if (value === "light") {
value = darkTheme;
}
else {
value = lightTheme;
}
}

var settings = this.state.settings;

settings[settingName] = value;

this.fetchAssetData((settingName === "currency") ? value : this.state.settings.currency);

this.setState({
settings: settings
});

if (settingName === "currency" || settingName === "datasource") {
this.fetchAssetData();
}

localStorage.setItem("settings", JSON.stringify(settings));
}

Expand Down Expand Up @@ -272,13 +307,11 @@ class App extends Component {
});
}

updateHoldings(event, asset){
let value = parseFloat(event.target.value);

updateHoldings(value, symbol){
var assets = this.state.data.assets;

if (value){
assets.find(asset => asset.symbol === asset.symbol.toUpperCase()).holdings = value;
if (value) {
assets.find(asset => asset.symbol === symbol).holdings = value;
}

this.storeData(assets);
Expand All @@ -303,38 +336,42 @@ class App extends Component {
render() {
return (
<div className="page">
<Header addCrypto={this.addCrypto.bind(this)} assets={this.state.data.assets} cryptoAssetData={this.state.cryptoassets} settings={this.state.settings} toggleShowSettings={this.toggleShowSettings.bind(this)}/>
<hr />
<div className="content">
<CardRow assets={this.state.data.assets} removeCrypto={this.removeCrypto.bind(this)} settings={this.state.settings} updateHoldings={this.updateHoldings.bind(this)} />
</div>
<Settings data={this.state.data} editSetting={this.editSetting.bind(this)} settings={this.state.settings} showSettings={this.state.showSettings} toggleShowSettings={this.toggleShowSettings.bind(this)} uploadData={this.uploadData.bind(this)} />
<Hotkeys
keyName="shift+/"
onKeyDown={this.toggleShowSettings.bind(this)}
/>
<Snackbar
action={
<React.Fragment>
<IconButton
aria-label="close"
color="inherit"
onClick={() => this.setState({dataUpdated: false})}
>
<CloseIcon />
</IconButton>
</React.Fragment>
}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
autoHideDuration={Number(this.state.settings.autoHideFetchNotification)}
key={this.state.timestamp}
message={`Prices updated: ${new Date(this.state.timestamp).toLocaleString()}`}
onClose={() => this.setState({dataUpdated: false})}
open={this.state.dataUpdated}
/>
<ThemeProvider theme={this.state.settings.theme || lightTheme}>
<CssBaseline />

<Header addCrypto={this.addCrypto.bind(this)} assets={this.state.data.assets} cryptoAssetData={this.state.cryptoassets} editSetting={this.editSetting.bind(this)} settings={this.state.settings} toggleShowSettings={this.toggleShowSettings.bind(this)}/>
<hr />
<div className="content">
<CardRow assets={this.state.data.assets} removeCrypto={this.removeCrypto.bind(this)} settings={this.state.settings} updateHoldings={this.updateHoldings.bind(this)} />
</div>
<Settings data={this.state.data} editSetting={this.editSetting.bind(this)} settings={this.state.settings} showSettings={this.state.showSettings} theme={this.state.settings.theme || lightTheme} toggleShowSettings={this.toggleShowSettings.bind(this)} uploadData={this.uploadData.bind(this)} />
<Hotkeys
keyName="shift+/"
onKeyDown={this.toggleShowSettings.bind(this)}
/>
<Snackbar
action={
<React.Fragment>
<IconButton
aria-label="close"
color="inherit"
onClick={() => this.setState({dataUpdated: false})}
>
<CloseIcon />
</IconButton>
</React.Fragment>
}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
autoHideDuration={Number(this.state.settings.autoHideFetchNotification)}
key={this.state.timestamp}
message={`Prices updated: ${new Date(this.state.timestamp).toLocaleString()}`}
onClose={() => this.setState({dataUpdated: false})}
open={this.state.dataUpdated}
/>
</ThemeProvider>
</div>
);
}
Expand Down
38 changes: 17 additions & 21 deletions src/Components/Card.js → src/Components/AssetCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'bootstrap/dist/css/bootstrap.min.css';
import FontAwesome from 'react-fontawesome';
import '../styles/Card.css';
import TextField from "@material-ui/core/TextField";
import {InputAdornment, Slider} from "@material-ui/core";
import {Card, InputAdornment, Slider} from "@material-ui/core";

function MyBalance(props) {
if (props.holdings > 0 && props.settings.showCardBalances) {
Expand All @@ -19,12 +19,11 @@ function MyBalance(props) {
)
}

class Card extends Component {
class AssetCard extends Component {
constructor(props){
super(props);
this.state ={
flip: false,
holdings: props.asset.holdings,
settings: props.settings,
simulatedPercentChange: 0,
simulatedPrice: props.asset.price,
Expand Down Expand Up @@ -114,7 +113,7 @@ class Card extends Component {
let back = this.state.flip ? '' : 'none';
return(
<div className="col-xs-12 col-sm-6 col-lg-4 card-container">
<div className="card">
<Card className="card">
<div className={(window.innerWidth <= 760) ? "row" : ""} style={{display: front}} onClick={() => this.toggleSettings()}>
<div className={(window.innerWidth <= 760) ? "ml-2 w-50" : ""}>
<FontAwesome
Expand All @@ -137,7 +136,7 @@ class Card extends Component {
{this.getPercentChange(this.props.asset.percent_change_1h, "1h")}
{this.getPercentChange(this.props.asset.percent_change_24h, "24h")}
{this.getPercentChange(this.props.asset.percent_change_7d, "7d")}
<MyBalance holdings={this.state.holdings} price={price} settings={this.state.settings} />
<MyBalance holdings={this.props.asset.holdings} price={price} settings={this.state.settings} />
</div>
</div>
</div>
Expand Down Expand Up @@ -166,18 +165,15 @@ class Card extends Component {
label="My Holdings"
onChange={
event => {
this.setState({
holdings: parseFloat(event.target.value)
});
this.props.updateHoldings(event, this.props.asset)
this.props.updateHoldings(parseFloat(event.target.value), this.props.asset.symbol)
}
}
size={"small"}
value={this.state.holdings || 0}
value={this.props.asset.holdings || 0}
variant="outlined"
/>

<MyBalance holdings={this.state.holdings} price={price} settings={this.state.settings} />
<MyBalance holdings={this.props.asset.holdings} price={price} settings={this.state.settings} />

<hr />

Expand All @@ -191,7 +187,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: event.target.value,
simulatedPrice: (((event.target.value * .01) * price) + price),
simulatedValue: ((((event.target.value * .01) * price) + price) * this.state.holdings),
simulatedValue: ((((event.target.value * .01) * price) + price) * this.props.asset.holdings),
simulatedCap: ((((event.target.value * .01) * price) + price) * this.props.asset.circulating_supply)
})
}
Expand All @@ -209,7 +205,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: value,
simulatedPrice: (((value * .01) * price) + price),
simulatedValue: ((((value * .01) * price) + price) * this.state.holdings),
simulatedValue: ((((value * .01) * price) + price) * this.props.asset.holdings),
simulatedCap: ((((value * .01) * price) + price) * this.props.asset.circulating_supply)
})
}
Expand All @@ -235,7 +231,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: (100 * ((event.target.value - price) / price)),
simulatedPrice: event.target.value,
simulatedValue: (event.target.value * this.state.holdings),
simulatedValue: (event.target.value * this.props.asset.holdings),
simulatedCap: (event.target.value * this.props.asset.circulating_supply)
})
}
Expand All @@ -252,14 +248,14 @@ class Card extends Component {
onChange={
event =>
this.setState({
simulatedPercentChange: (100 * (((event.target.value / this.state.holdings) - price) / price)),
simulatedPrice: (event.target.value / this.state.holdings),
simulatedPercentChange: (100 * (((event.target.value / this.props.asset.holdings) - price) / price)),
simulatedPrice: (event.target.value / this.props.asset.holdings),
simulatedValue: event.target.value,
simulatedCap: ((event.target.value / this.state.holdings) * this.props.asset.circulating_supply)
simulatedCap: ((event.target.value / this.props.asset.holdings) * this.props.asset.circulating_supply)
})
}
size={"small"}
value={this.getLocalizedPrice(this.state.simulatedValue) || this.getLocalizedPrice(this.state.holdings * price)}
value={this.getLocalizedPrice(this.state.simulatedValue) || this.getLocalizedPrice(this.props.asset.holdings * price)}
variant="outlined"
/>

Expand All @@ -273,7 +269,7 @@ class Card extends Component {
this.setState({
simulatedPercentChange: (100 * ((event.target.value - (this.props.asset.circulating_supply * price)) / (this.props.asset.circulating_supply * price))),
simulatedPrice: (event.target.value / this.props.asset.circulating_supply),
simulatedValue: ((event.target.value / this.props.asset.circulating_supply) * this.state.holdings),
simulatedValue: ((event.target.value / this.props.asset.circulating_supply) * this.props.asset.holdings),
simulatedCap: event.target.value
})
}
Expand All @@ -284,10 +280,10 @@ class Card extends Component {
</div>
</div>
</div>
</div>
</Card>
</div>
)
}
}

export default Card;
export default AssetCard;
Loading

0 comments on commit b2bc411

Please sign in to comment.