Repair scale of the graph. Add trigger and prognosis functionality
parent
721d05a42c
commit
360e725b21
|
|
@ -0,0 +1,48 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import { checkPrognosis } from '../../stores/exchange/duck/operations'
|
||||
|
||||
import '../../styles/indexExchange.scss'
|
||||
|
||||
const ExchangePrognosis = ({
|
||||
user,
|
||||
exchange, checkPrognosis }) => {
|
||||
|
||||
const inputPrognosis = React.createRef()
|
||||
|
||||
const checkNewPrognosis = () => {
|
||||
if ( inputPrognosis.current.value > 0 ) {
|
||||
let prognosis = {
|
||||
price: inputPrognosis.current.value,
|
||||
}
|
||||
checkPrognosis( prognosis )
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='exchangePrognosisDiv'>
|
||||
<input
|
||||
placeholder='Write the amount to exchange forecast'
|
||||
onChange={ () => checkNewPrognosis() }
|
||||
ref={ inputPrognosis }>
|
||||
</input>
|
||||
<p>Forecast: { Number((exchange.prognosis.price_forecast).toFixed(2)) } PLN</p>
|
||||
<p>Percent: { Number((exchange.prognosis.percent_of_difference).toFixed(3)) } %</p>
|
||||
<p>Course on payment: { exchange.prognosis.course_on_payment } PLN</p>
|
||||
<p>AVG: { Number((exchange.prognosis.svg_of_all).toFixed(2)) }</p>
|
||||
<p>Date: { exchange.prognosis.date_of_transaction }</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
user: state.user,
|
||||
exchange: state.exchange
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
checkPrognosis: exchange => dispatch( checkPrognosis(exchange) )
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps,mapDispatchToProps)(ExchangePrognosis)
|
||||
|
|
@ -1,22 +1,54 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import { getChart, getUserTriggers, getUserNotifications, getUserTransactions } from '../../stores/exchange/duck/operations'
|
||||
import { getChart, getUserTriggers, getUserNotifications, getUserTransactions, addTrigger } from '../../stores/exchange/duck/operations'
|
||||
|
||||
import '../../styles/indexExchange.scss'
|
||||
|
||||
const ExchangeTriggerAdd = ({
|
||||
user,
|
||||
exchange, getChart, getUserTriggers, getUserNotifications, getUserTransactions,
|
||||
mousePosition }) => {
|
||||
exchange, getChart, getUserTriggers, getUserNotifications, getUserTransactions, addTrigger,
|
||||
triggerValue }) => {
|
||||
|
||||
useEffect( () => { getUserTriggers(user) }, [] )
|
||||
useEffect( () => { getUserTriggers(user.id) }, [] )
|
||||
|
||||
const [inputValue, setInputValue] = useState( triggerValue )
|
||||
const [message, setMessage] = useState('')
|
||||
|
||||
const triggerValueAdd = React.createRef()
|
||||
|
||||
const addNewTrigger = (event) => {
|
||||
event.preventDefault()
|
||||
if ( triggerValue !== 0 ) {
|
||||
let newTrigger = {
|
||||
user_id: user.id,
|
||||
course_values_for_trigger: triggerValue,
|
||||
token: user.token
|
||||
}
|
||||
addTrigger( newTrigger )
|
||||
setMessage('Trigger has been added')
|
||||
}
|
||||
else
|
||||
setMessage('Trigger add error')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='exchangeTriggerDativeY'
|
||||
style={ { marginTop: mousePosition.y + 'px' } }>
|
||||
|
||||
<div className='exchangeTriggerDiv'>
|
||||
<form onSubmit={ addNewTrigger }>
|
||||
<p>Trigger value: { triggerValue } zł</p>
|
||||
<button>
|
||||
Add Trigger
|
||||
</button>
|
||||
</form>
|
||||
<p>{ user.login } Triggers:</p>
|
||||
<p>{ message }</p>
|
||||
<div className='triggerItemList'>
|
||||
{ exchange.userTriggers
|
||||
.sort( (a, b) => b.id - a.id )
|
||||
.map( (trigger, key) => (
|
||||
<div key={ key } className='triggerItem'><p>{ key }. Value: { trigger.course_values_for_trigger } PLN, Date: { trigger.date_of_trigger }, Status { trigger.status === 1 ? 'Enabled' : 'Disabled' }</p></div>
|
||||
) ) }
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -27,10 +59,8 @@ const mapStateToProps = state => ({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
getChart: exchange => dispatch( getChart(exchange) ),
|
||||
getUserTriggers: exchange => dispatch( getUserTriggers(exchange) ),
|
||||
getUserNotifications: exchange => dispatch( getUserNotifications(exchange) ),
|
||||
getUserTransactions: exchange => dispatch( getUserTransactions(exchange) )
|
||||
addTrigger: exchange => dispatch( addTrigger(exchange) )
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps,mapDispatchToProps)(ExchangeTriggerAdd)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ import { connect } from 'react-redux'
|
|||
|
||||
import { getChart, getUserTriggers, getUserNotifications, getUserTransactions } from '../../stores/exchange/duck/operations'
|
||||
|
||||
import { useInterval } from '../useInterval'
|
||||
|
||||
import ExchangeTriggerAdd from './exchangeTriggerAdd'
|
||||
import ExchangePrognosis from './exchangePrognosis'
|
||||
|
||||
import '../../styles/indexExchange.scss'
|
||||
|
||||
|
|
@ -11,12 +14,15 @@ const IndexExchange = ({
|
|||
user,
|
||||
exchange, getChart, getUserTriggers, getUserNotifications, getUserTransactions }) => {
|
||||
|
||||
useEffect( () => { getChart() }, [] )
|
||||
useEffect( () => { getUserTriggers() }, [] )
|
||||
let fifteenMinuts = 1500000
|
||||
|
||||
useInterval( () => {
|
||||
getChart()
|
||||
}, fifteenMinuts )
|
||||
|
||||
const [candleInfo, setCandleInfo] = useState( { Open: 0, Close: 0, Min: 0, Max: 0, Vol: 0 } )
|
||||
|
||||
const [mousePosition, setMousePosition] = useState( { x: 0, y: 0 } )
|
||||
const [triggerValue, setTriggerValue] = useState(0)
|
||||
|
||||
const colorGreen = {
|
||||
background: 'green'//'rgba(0,93,0,1)',
|
||||
|
|
@ -37,8 +43,8 @@ const IndexExchange = ({
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
let pixelScale = ( exchange.candles.graphMax - exchange.candles.graphMin ) / 590
|
||||
let cursorValue = exchange.candles.graphMax - ( pixelScale * ( mousePosition.y - 175 ) )
|
||||
|
||||
const getMousePosition = (event) => {
|
||||
setMousePosition( { x: event.pageX, y: event.pageY } )
|
||||
|
|
@ -50,12 +56,13 @@ const IndexExchange = ({
|
|||
<div className={ user.id > -1 ? 'exchangeChartUser' : 'exchangeChartGuest' }>
|
||||
<div className='chart'
|
||||
onMouseOver={ event => getMousePosition(event) }
|
||||
onClick={ () => setTriggerValue( parseInt(cursorValue) ) }
|
||||
style={ { width: exchange.candles.candlesCount * 15 + 'px' } }>
|
||||
{ user.id > -1 ? (
|
||||
<div>
|
||||
<div className='exchangeTriggerDativeY'
|
||||
style={ { transform: 'translateY(' + (mousePosition.y - 175) + 'px)' } }>
|
||||
<p>{ ( exchange.candles.graphMax - ( pixelScale * ( mousePosition.y - 175 ) ) ) }</p>
|
||||
<p>{ parseInt(cursorValue) } PLN</p>
|
||||
</div>
|
||||
<div className='exchangeTriggerDativeX'
|
||||
style={ { transform: 'translateX(' + (mousePosition.x) + 'px)' } }>
|
||||
|
|
@ -71,12 +78,12 @@ const IndexExchange = ({
|
|||
let highValue = candle.Open > candle.Close ? candle.Open : candle.Close
|
||||
let lowValue = candle.Open < candle.Close ? candle.Open : candle.Close
|
||||
|
||||
let scaleProperties = 8
|
||||
let scaleProperties = 10
|
||||
|
||||
let chartScaleY = (exchange.candles.graphMax - candle.Max) / scaleProperties
|
||||
let chartScaleY = (exchange.candles.graphMax - candle.Max) / pixelScale
|
||||
|
||||
let onePercentScaleY = 100 / chartScaleY
|
||||
let difference = (( highValue - lowValue ) / onePercentScaleY ) / scaleProperties
|
||||
let difference = ( highValue - lowValue ) / pixelScale
|
||||
|
||||
if ( parseInt(difference) === 0 )
|
||||
difference = 1
|
||||
|
|
@ -93,26 +100,22 @@ const IndexExchange = ({
|
|||
style={ { paddingTop: chartScaleY + 'px' } }>
|
||||
<div
|
||||
className='candleMaxValue'
|
||||
style={ { height: parseInt( (candle.Max - highValue ) / scaleProperties ) + 'px', background: color }}>
|
||||
style={ { height: parseInt( (candle.Max - highValue ) / pixelScale ) + '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 ) / scaleProperties ) + 'px', background: color }}>
|
||||
style={ { height: parseInt( ( lowValue - candle.Min ) / pixelScale ) + 'px', background: color }}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='sectionVolumen'>
|
||||
<div className='volumen'
|
||||
style={ { height: candle.Volume + 'px' } }>
|
||||
style={ { height: candle.Volume / 1.5 + 'px' } }>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -125,13 +128,22 @@ const IndexExchange = ({
|
|||
</div>
|
||||
<div className={ user.id > -1 ? 'exchangeInterface' : 'exchangeEmptySpace' }>
|
||||
<div className='candleInformation'>
|
||||
<p>Open: { candleInfo.Open },</p>
|
||||
<p>Close: { candleInfo.Close },</p>
|
||||
<p>Max: { candleInfo.Max },</p>
|
||||
<p>Min: { candleInfo.Min },</p>
|
||||
<p>Open: { candleInfo.Open } PLN,</p>
|
||||
<p>Close: { candleInfo.Close } PLN,</p>
|
||||
<p>Max: { candleInfo.Max } PLN,</p>
|
||||
<p>Min: { candleInfo.Min } PLN,</p>
|
||||
<p>Volume: { candleInfo.Vol },</p>
|
||||
<p>Date: { candleInfo.Date }</p>
|
||||
</div>
|
||||
{ user.id > -1 ? (
|
||||
<div>
|
||||
<ExchangeTriggerAdd triggerValue={ triggerValue } />
|
||||
<ExchangePrognosis />
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { getSubjectsThread } from '../stores/subjects/duck/operations'
|
||||
|
||||
import '../styles/index.scss'
|
||||
|
||||
const Index = ({subjects, getSubjectsThread}) =>{
|
||||
|
||||
useEffect( () => { getSubjectsThread() }, [])
|
||||
|
||||
return <ul>
|
||||
{subjects.list.map(subject => <li>{subject}</li>)}
|
||||
</ul>
|
||||
}
|
||||
|
||||
// do odczytu globalnego state'a
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
subjects: state.subjects
|
||||
})
|
||||
|
||||
// do modyfikacji globalnego state'a
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
getSubjectsThread: () => dispatch( getSubjectsThread() )
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Index)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import actions from '../stores/subjects/duck/actions'
|
||||
|
||||
const IndexForm = (props) => {
|
||||
|
||||
const subjectInput = React.createRef()
|
||||
|
||||
const addSubject = (event) => {
|
||||
event.preventDefault()
|
||||
props.add(subjectInput.current.value)
|
||||
|
||||
subjectInput.current.value = ''
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={addSubject}>
|
||||
<input ref={subjectInput} />
|
||||
<button type='submit'>Add Subject</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
add: subject => dispatch(actions.add(subject))
|
||||
})
|
||||
|
||||
export default connect(null, mapDispatchToProps)(IndexForm)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
|
||||
export const useInterval = (callback, delay) => {
|
||||
|
||||
const savedCallback = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
savedCallback.current = callback;
|
||||
}, [callback]);
|
||||
|
||||
useEffect(() => {
|
||||
function tick() {
|
||||
savedCallback.current();
|
||||
}
|
||||
if (delay !== null) {
|
||||
let id = setInterval(tick, delay);
|
||||
return () => clearInterval(id);
|
||||
}
|
||||
}, [delay]);
|
||||
}
|
||||
|
|
@ -16,6 +16,14 @@ const setTransactions = item => ({
|
|||
type: types.GET_USER_TRANSACTIONS, item
|
||||
})
|
||||
|
||||
const addNewTrigger = item => ({
|
||||
type: types.ADD_NEW_TRIGGER, item
|
||||
})
|
||||
|
||||
const setNewPrognosis = item => ({
|
||||
type: types.NEW_PROGNOSIS, item
|
||||
})
|
||||
|
||||
const reset = item => ({
|
||||
type: types.RESET, item
|
||||
})
|
||||
|
|
@ -25,5 +33,7 @@ export default {
|
|||
setTriggers,
|
||||
setNotifications,
|
||||
setTransactions,
|
||||
addNewTrigger,
|
||||
setNewPrognosis,
|
||||
reset
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ const fetchGetChart = async () => {
|
|||
const fetchGetUserTriggers = async (userID) => {
|
||||
const response = await
|
||||
fetch (
|
||||
'http://localhost:8001/index/trigger/' + userID, {
|
||||
'http://localhost:8001/index/user/' + userID + '/trigger', {
|
||||
method: 'GET',
|
||||
credential: 'same-origin'
|
||||
})
|
||||
|
|
@ -44,26 +44,58 @@ const fetchGetUserNotifications = async (userID) => {
|
|||
return json
|
||||
}
|
||||
|
||||
const fetchAddTrigger = async (data) => {
|
||||
fetch (
|
||||
'http://localhost:8001/index/user/' + data.user_id + '/trigger', {
|
||||
method: 'POST',
|
||||
credential: 'same-origin',
|
||||
body: JSON.stringify(data)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const fetchPrognosis = async (data) => {
|
||||
const response = await fetch (
|
||||
'http://localhost:8001/index/exchange/1800/prognosis/' + data.price, {
|
||||
method: 'GET',
|
||||
credential: 'same-origin'
|
||||
}
|
||||
)
|
||||
const json = response.json()
|
||||
return json
|
||||
}
|
||||
|
||||
export const getChart = () =>
|
||||
async (dispatch) => {
|
||||
const chart = await fetchGetChart()
|
||||
dispatch(actions.setChart(chart))
|
||||
}
|
||||
|
||||
export const getUserTriggers = () =>
|
||||
export const getUserTriggers = (userID) =>
|
||||
async (dispatch) => {
|
||||
const triggers = await fetchGetUserTriggers()
|
||||
dispatch(actions.setUserTriggers(triggers))
|
||||
const triggers = await fetchGetUserTriggers(userID)
|
||||
dispatch(actions.setTriggers(triggers))
|
||||
}
|
||||
|
||||
export const getUserTransactions = () =>
|
||||
export const getUserTransactions = (userID) =>
|
||||
async (dispatch) => {
|
||||
const transactions = await fetchGetUserTransactions()
|
||||
dispatch(actions.setUserTransactions(transactions))
|
||||
const transactions = await fetchGetUserTransactions(userID)
|
||||
dispatch(actions.setTransactions(transactions))
|
||||
}
|
||||
|
||||
export const getUserNotifications = () =>
|
||||
export const getUserNotifications = (userID) =>
|
||||
async (dispatch) => {
|
||||
const notifications = await fetchGetUserNotifications()
|
||||
dispatch(actions.setUserNotifications(notifications))
|
||||
const notifications = await fetchGetUserNotifications(userID)
|
||||
dispatch(actions.setNotifications(notifications))
|
||||
}
|
||||
|
||||
export const addTrigger = (data) =>
|
||||
async (dispatch) => {
|
||||
await fetchAddTrigger(data)
|
||||
}
|
||||
|
||||
export const checkPrognosis = (data) =>
|
||||
async (dispatch) => {
|
||||
const prognosis = await fetchPrognosis(data)
|
||||
dispatch(actions.setNewPrognosis(prognosis))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ const INITIAL_STATE = {
|
|||
candles: [],
|
||||
userTriggers: [],
|
||||
userNotifications: [],
|
||||
userTransactions: []
|
||||
userTransactions: [],
|
||||
prognosis: {}
|
||||
}
|
||||
|
||||
const exchangeReducer = (state = INITIAL_STATE, action) => {
|
||||
|
|
@ -29,6 +30,11 @@ const exchangeReducer = (state = INITIAL_STATE, action) => {
|
|||
...state,
|
||||
userTransactions: action.item
|
||||
}
|
||||
case types.NEW_PROGNOSIS:
|
||||
return {
|
||||
...state,
|
||||
prognosis: action.item
|
||||
}
|
||||
case types.RESET:
|
||||
return {
|
||||
...state,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ 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 ADD_NEW_TRIGGER = 'ADD_NEW_TRIGGER'
|
||||
const NEW_PROGNOSIS = 'NEW_PROGNOSIS'
|
||||
const RESET = 'RESET'
|
||||
|
||||
export default {
|
||||
|
|
@ -9,5 +11,7 @@ export default {
|
|||
GET_USER_TRIGGERS,
|
||||
GET_USER_NOTIFICATIONS,
|
||||
GET_USER_TRANSACTIONS,
|
||||
ADD_NEW_TRIGGER,
|
||||
NEW_PROGNOSIS,
|
||||
RESET
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,3 +140,82 @@
|
|||
background-color: rgba(117,82,29,1);
|
||||
transform: margin 700ms;
|
||||
}
|
||||
|
||||
@mixin gapBetweenSectionsEx {
|
||||
border-right: 2px dashed;
|
||||
border-color: rgba(117,82,29,0.7);
|
||||
}
|
||||
|
||||
@mixin exchangeDivInterface {
|
||||
width: 32%;
|
||||
height: 160px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
float:left;
|
||||
background: rgba(0,0,0,0.2);
|
||||
overflow: hidden;
|
||||
|
||||
@include gapBetweenSectionsEx
|
||||
}
|
||||
|
||||
.exchangeTriggerDiv {
|
||||
@include exchangeDivInterface
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
float: left;
|
||||
display: flex;
|
||||
|
||||
p {
|
||||
padding-top: 10px;
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
button {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
float: left;
|
||||
width: 50%;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.triggerItemList {
|
||||
width: 100%;
|
||||
height: 75px;
|
||||
overflow-y: scroll;
|
||||
|
||||
.triggerItem {
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
|
||||
p {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.exchangePrognosisDiv {
|
||||
@include exchangeDivInterface
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 50%;
|
||||
height: 10px;
|
||||
float: left;
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
|
||||
&:last-of-type {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue