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

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 movementsReducer from './movements/duck'
import commentReducer from './comments/duck'
import subjectReducer from './subjects/duck'
import threadReducer from './threads/duck'
import userReducer from './user/duck'
import exchangeReducer from './exchange/duck'
const rootReducer = combineReducers({
user: userReducer,
threads: threadReducer,
subjects: subjectReducer,
comments: commentReducer,
movements: movementsReducer
movements: movementsReducer,
exchange: exchangeReducer
})
export default rootReducer

View File

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

View File

@ -5,6 +5,17 @@
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 {
width: 200px;
height: 35px;

View File

@ -5,7 +5,7 @@ body {
overflow-y: hidden;
::-webkit-scrollbar {
display: none;
@include scrollStyle
}
input {
@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
}