add exchange graph

front
TBS093A 2020-01-16 01:08:02 +01:00
parent a731739178
commit d03d8bb92d
12 changed files with 403 additions and 11 deletions

View File

@ -1,19 +1,135 @@
import React from 'react' import React, { useState, useEffect } from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import '../../styles/index.scss' import { getChart, getTriggers, getNotifications, getTransactions } from '../../stores/exchange/duck/operations'
const IndexExchange = ({ user }) => { import '../../styles/indexExchange.scss'
const IndexExchange = ({
user,
exchange, getChart, getTriggers, getNotifications, getTransactions }) => {
useEffect( () => { getChart() }, [] )
const [candleInfo, setCandleInfo] = useState( { Open: 0, Close: 0, Min: 0, Max: 0, Vol: 0 } )
const colorGreen = {
background: 'green',
}
const colorRed = {
background: 'red',
}
const getCandleInformation = (candle) => {
setCandleInfo( {
Open: candle.Open,
Close: candle.Close,
Min: candle.Min,
Max: candle.Max,
Vol: candle.Volume,
Date: candle.Date
}
)
}
return ( return (
<div> <div className='indexExchange'>
<div className={ user.id > -1 ? 'exchangeChartUser' : 'exchangeChartGuest' }>
<div className='chart' style={ { width: exchange.candles.candlesCount * 15 + 'px' } }>
{ exchange.candles.candles.map( (candle, key) => {
const color = candle.Open > candle.Close ? colorRed.background : colorGreen.background
let highValue = candle.Open > candle.Close ? candle.Open : candle.Close
let lowValue = candle.Open < candle.Close ? candle.Open : candle.Close
let difference = highValue - lowValue
let chartScaleY = (exchange.candles.graphMax - candle.Max) / 8
if ( difference > 0 && difference < 10 )
difference *= 2
else if ( difference > 50 && difference < 100 )
difference /= 2
else if ( difference >= 100 && difference <= 200 )
difference /= 3
else if ( difference > 200 )
difference = difference % 100
return (
<div
key={ key }
className='sectionChart'
onMouseOver={ () => getCandleInformation(candle) }>
<div className='sectionCandle'>
<div
className='candle'
style={ { paddingTop: chartScaleY + 'px' } }
>
<div
className='candleMaxValue'
style={ { height: parseInt( (candle.Max - highValue ) / 2 ) + 'px',
background: color }
}>
</div>
<div
className='candleHigh'
style={
{ height: parseInt( difference ) + 'px',
background: color }
}>
</div>
<div
className='candleLow'
style={ { height: parseInt( difference ) + 'px',
background: color }
}>
</div>
<div
className='candleMinValue'
style={ { height: parseInt( ( lowValue - candle.Min ) / 2 ) + 'px',
background: color }
}>
</div>
</div>
</div>
<div className='sectionVolumen'>
<div className='volumen'
style={ { height: candle.Volume + 'px' } }>
</div>
</div>
</div>
)
}
)
}
</div>
</div>
<div className={ user.id > -1 ? 'exchangeInterface' : 'emptySpaceExchange' }>
<div>
<p>Open: { candleInfo.Open }, Close: { candleInfo.Close }</p>
<p>Max: { candleInfo.Max }, Min: { candleInfo.Min }</p>
<p>Volume: { candleInfo.Vol }</p>
<p>Date: { candleInfo.Date }</p>
</div>
</div>
</div> </div>
) )
} }
const mapStateToProps = state => ({ const mapStateToProps = state => ({
user: state.user, user: state.user,
exchange: state.exchange
}) })
const mapDispatchToProps = dispatch => ({
getChart: exchange => dispatch( getChart(exchange) ),
getTriggers: exchange => dispatch( getTriggers(exchange) ),
getNotifications: exchange => dispatch( getNotifications(exchange) ),
getTransactions: exchange => dispatch( getTransactions(exchange) )
})
export default connect(mapStateToProps,null)(IndexExchange) export default connect(mapStateToProps,mapDispatchToProps)(IndexExchange)

View File

@ -1,9 +1,10 @@
import React from 'react' import React, {useEffect} from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
// Operations Redux // Operations Redux
import { createSession, deleteSession, updateSession, registerUser } from '../stores/user/duck/operations' import { createSession, deleteSession, updateSession, registerUser } from '../stores/user/duck/operations'
import { getChart } from '../stores/exchange/duck/operations'
// Actions Redux // Actions Redux
@ -28,9 +29,12 @@ import BtcLogo from '../images/BtcLogo.png'
import ForumLogo from '../images/ForumLogo.png' import ForumLogo from '../images/ForumLogo.png'
const IndexInterface = ({ const IndexInterface = ({
user, movements, user, movements, exchange,
createSession, deleteSession, updateSession, registerUser, createSession, deleteSession, updateSession, registerUser,
setRegister, setEdit, setForum, setExchange, setAdminPanel, resetMovements}) => { setRegister, setEdit, setForum, setExchange, setAdminPanel, resetMovements,
getChart }) => {
useEffect( () => { getChart() }, [] )
const loginInput = React.createRef() const loginInput = React.createRef()
const passwordInput = React.createRef() const passwordInput = React.createRef()
@ -304,6 +308,7 @@ const IndexInterface = ({
const mapStateToProps = state => ({ const mapStateToProps = state => ({
user: state.user, user: state.user,
exchange: state.exchange,
movements: state.movements movements: state.movements
}) })
@ -318,7 +323,9 @@ const mapDispatchToProps = dispatch => ({
setExchange: movements => dispatch( actions.exchange() ), setExchange: movements => dispatch( actions.exchange() ),
setForum: movements => dispatch( actions.forum() ), setForum: movements => dispatch( actions.forum() ),
setAdminPanel: movements => dispatch( actions.adminPanel() ), setAdminPanel: movements => dispatch( actions.adminPanel() ),
resetMovements: movements => dispatch( actions.reset() ) resetMovements: movements => dispatch( actions.reset() ),
getChart: exchange => dispatch( getChart(exchange) )
}) })
export default connect(mapStateToProps, mapDispatchToProps)(IndexInterface) export default connect(mapStateToProps, mapDispatchToProps)(IndexInterface)

View File

@ -0,0 +1,29 @@
import types from './types'
const setChart = item => ({
type: types.GET_CANDLES_CHART, item
})
const setTriggers = item => ({
type: types.GET_USER_TRIGGERS, item
})
const setNotifications = item => ({
type: types.GET_USER_NOTIFICATIONS, item
})
const setTransactions = item => ({
type: types.GET_USER_TRANSACTIONS, item
})
const reset = item => ({
type: types.RESET, item
})
export default {
setChart,
setTriggers,
setNotifications,
setTransactions,
reset
}

View File

@ -0,0 +1,5 @@
import exchangeReducer from './reducers'
export { default as exchangeTypes } from './types'
export { default as exchangeActions } from './actions'
export default exchangeReducer

View File

@ -0,0 +1,69 @@
import actions from './actions'
const fetchGetChart = async () => {
const response = await
fetch (
'http://localhost:8001/index/exchange/' + 1800, {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchGetUserTriggers = async (userID) => {
const response = await
fetch (
'http://localhost:8001/index/trigger/' + userID, {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchGetUserTransactions = async (userID) => {
const response = await
fetch (
'http://localhost:8001/index/user/' + userID + '/transaction', {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
const fetchGetUserNotifications = async (userID) => {
const response = await
fetch (
'http://localhost:8001/index/user/' + userID + '/notification', {
method: 'GET',
credential: 'same-origin'
})
const json = await response.json()
return json
}
export const getChart = () =>
async (dispatch) => {
const chart = await fetchGetChart()
dispatch(actions.setChart(chart))
}
export const getGetUserTriggers = () =>
async (dispatch) => {
const triggers = await fetchGetUserTriggers()
dispatch(actions.setUserTriggers(triggers))
}
export const getUserTransactions = () =>
async (dispatch) => {
const transactions = await fetchGetUserTransactions()
dispatch(actions.setUserTransactions(transactions))
}
export const getUserNotifications = () =>
async (dispatch) => {
const notifications = await fetchGetUserNotifications()
dispatch(actions.setUserNotifications(notifications))
}

View File

@ -0,0 +1,44 @@
import types from './types'
const INITIAL_STATE = {
candles: [],
userTriggers: [],
userNotifications: [],
userTransactions: []
}
const exchangeReducer = (state = INITIAL_STATE, action) => {
switch(action.type) {
case types.GET_CANDLES_CHART:
return {
...state,
candles: action.item
}
case types.GET_USER_TRIGGERS:
return {
...state,
userTriggers: action.item
}
case types.GET_USER_NOTIFICATIONS:
return {
...state,
userNotifications: action.item
}
case types.GET_USER_TRANSACTIONS:
return {
...state,
userTransactions: action.item
}
case types.RESET:
return {
...state,
userTriggers: [],
userNotifications: [],
userTransactions: []
}
default:
return state
}
}
export default exchangeReducer

View File

@ -0,0 +1,13 @@
const GET_CANDLES_CHART = 'GET_CANDLES_CHART'
const GET_USER_TRIGGERS = 'GET_USER_TRIGGERS'
const GET_USER_NOTIFICATIONS = 'GET_USER_NOTIFICATIONS'
const GET_USER_TRANSACTIONS = 'GET_USER_TRANSACTIONS'
const RESET = 'RESET'
export default {
GET_CANDLES_CHART,
GET_USER_TRIGGERS,
GET_USER_NOTIFICATIONS,
GET_USER_TRANSACTIONS,
RESET
}

View File

@ -1,16 +1,21 @@
import { combineReducers } from 'redux' import { combineReducers } from 'redux'
import movementsReducer from './movements/duck' import movementsReducer from './movements/duck'
import commentReducer from './comments/duck' import commentReducer from './comments/duck'
import subjectReducer from './subjects/duck' import subjectReducer from './subjects/duck'
import threadReducer from './threads/duck' import threadReducer from './threads/duck'
import userReducer from './user/duck' import userReducer from './user/duck'
import exchangeReducer from './exchange/duck'
const rootReducer = combineReducers({ const rootReducer = combineReducers({
user: userReducer, user: userReducer,
threads: threadReducer, threads: threadReducer,
subjects: subjectReducer, subjects: subjectReducer,
comments: commentReducer, comments: commentReducer,
movements: movementsReducer movements: movementsReducer,
exchange: exchangeReducer
}) })
export default rootReducer export default rootReducer

View File

@ -26,6 +26,7 @@ const userReducer = (state = INITIAL_STATE, action) => {
} }
case types.LOGOUT_USER: case types.LOGOUT_USER:
return { return {
id: -1,
isActive: false isActive: false
} }
default: default:

View File

@ -5,6 +5,17 @@
margin: auto; margin: auto;
} }
@mixin scrollStyle {
margin-top: 5px;
margin-bottom: 5px;
border: 0px;
border-radius: 10px;
font-size: 12pt;
text-align: center;
color: rgba(111,108,106,1);
background-color: rgba(22,28,29,0.6);
}
@mixin inputStyle { @mixin inputStyle {
width: 200px; width: 200px;
height: 35px; height: 35px;

View File

@ -5,7 +5,7 @@ body {
overflow-y: hidden; overflow-y: hidden;
::-webkit-scrollbar { ::-webkit-scrollbar {
display: none; @include scrollStyle
} }
input { input {
@include inputStyle @include inputStyle

View File

@ -0,0 +1,92 @@
@import 'elements';
.indexExchange {
position: relative;
z-index: 0;
width: 100%;
height: auto;
padding-top: 20vh;
margin-left: auto;
margin-right: auto;
}
@mixin centerEx {
margin-left: auto;
margin-right: auto;
}
@mixin exchangeChart {
width: 100%;
height: 600px;
overflow-y: hidden;
overflow-x: scroll;
.chart {
height: 100%;
@include centerEx
.sectionChart {
width: 10px;
height: 100%;
margin-right: 5px;
float: left;
.sectionCandle {
width: 100%;
height: 400px;
@include centerEx
.candle {
width: 100%;
height: auto;
.candleMaxValue {
@include centerEx
width: 1px;
}
.candleHigh {
width: 100%;
}
.candleLow {
width: 100%;
}
.candleMinValue {
@include centerEx
width: 1px;
}
}
}
.sectionVolumen {
width: 100%;
height: 200px;
@include centerEx
.volumen {
width: 100%;
height: 20px;
background: gray;
opacity: 0.8;
}
}
}
}
}
.exchangeChartGuest {
@include exchangeChart
margin-top: 5vh;
}
.exchangeChartUser {
@include exchangeChart
}