budget chart vue component
This commit is contained in:
parent
d882c552dc
commit
22dc20ab73
@ -1,39 +1,90 @@
|
|||||||
import * as d3 from 'd3'
|
import * as d3 from 'd3'
|
||||||
import { format } from 'date-fns'
|
import { format } from 'date-fns'
|
||||||
|
import { abbreviateDollars, formatDollars } from '../../lib/dollars'
|
||||||
|
|
||||||
|
const TOP_OFFSET = 20
|
||||||
|
const BOTTOM_OFFSET = 60
|
||||||
|
const CHART_HEIGHT = 360
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'budget-chart',
|
name: 'budget-chart',
|
||||||
props: {
|
props: {
|
||||||
currentMonth: String,
|
currentMonth: String,
|
||||||
months: Object
|
months: Object,
|
||||||
|
budget: String
|
||||||
},
|
},
|
||||||
|
|
||||||
data: function () {
|
data: function () {
|
||||||
|
const heightScale = this.budget / (CHART_HEIGHT - TOP_OFFSET - BOTTOM_OFFSET)
|
||||||
return {
|
return {
|
||||||
numMonths: 10,
|
numMonths: 10,
|
||||||
focusedMonthPosition: 4, // 5th spot in zero-based index,
|
focusedMonthPosition: 4,
|
||||||
height: 300,
|
height: CHART_HEIGHT,
|
||||||
|
heightScale,
|
||||||
|
budgetHeight: CHART_HEIGHT - BOTTOM_OFFSET - (this.budget / heightScale),
|
||||||
|
baseHeight: CHART_HEIGHT - BOTTOM_OFFSET,
|
||||||
width: 0,
|
width: 0,
|
||||||
displayedMonths: []
|
displayedMonths: [],
|
||||||
|
spendPath: '',
|
||||||
|
projectedPath: '',
|
||||||
|
displayBudget: formatDollars(parseFloat(this.budget))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
console.log(this.displayedMonths)
|
|
||||||
this._setDisplayedMonths()
|
this._setDisplayedMonths()
|
||||||
this._setMetrics()
|
this._setMetrics()
|
||||||
|
addEventListener('resize', this._setMetrics)
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
_setMetrics: function () {
|
_setMetrics: function () {
|
||||||
this.width = this.$refs.panel.clientWidth
|
this.width = this.$refs.panel.clientWidth
|
||||||
// for (let i = 0; i < this.numMonths; i++) {
|
this.spendPath = ''
|
||||||
// this.displayedMonths[i].metrics.x = (this.width / this.numMonths)
|
this.projectedPath = ''
|
||||||
// }
|
|
||||||
|
let lastSpend = 0
|
||||||
|
let lastSpendPoint = ''
|
||||||
|
|
||||||
|
for (let i = 0; i < this.numMonths; i++) {
|
||||||
|
const { metrics, budget } = this.displayedMonths[i]
|
||||||
|
const blockWidth = (this.width / this.numMonths)
|
||||||
|
const blockX = blockWidth * i
|
||||||
|
const spend = budget
|
||||||
|
? budget.spend || lastSpend
|
||||||
|
: 0
|
||||||
|
const cumulative = budget
|
||||||
|
? budget.cumulative || budget.projected
|
||||||
|
: 0
|
||||||
|
const barHeight = spend / this.heightScale
|
||||||
|
lastSpend = spend
|
||||||
|
const cumulativeY = this.height - (cumulative / this.heightScale) - BOTTOM_OFFSET
|
||||||
|
const cumulativeX = blockX + blockWidth/2
|
||||||
|
const cumulativePoint = `${cumulativeX} ${cumulativeY}`
|
||||||
|
|
||||||
|
this.displayedMonths[i].metrics = Object.assign(metrics, {
|
||||||
|
blockWidth,
|
||||||
|
blockX,
|
||||||
|
barHeight,
|
||||||
|
barWidth: 30,
|
||||||
|
barX: blockX + (blockWidth/2 - 15),
|
||||||
|
barY: this.height - barHeight - BOTTOM_OFFSET,
|
||||||
|
cumulativeR: 2.5,
|
||||||
|
cumulativeY,
|
||||||
|
cumulativeX
|
||||||
|
})
|
||||||
|
|
||||||
|
if (budget && budget.spend) {
|
||||||
|
this.spendPath += this.spendPath === '' ? 'M' : ' L'
|
||||||
|
this.spendPath += cumulativePoint
|
||||||
|
lastSpendPoint = cumulativePoint
|
||||||
|
}
|
||||||
|
|
||||||
|
if (budget && budget.projected) {
|
||||||
|
this.projectedPath += this.projectedPath === '' ? `M${lastSpendPoint} L` : ' L'
|
||||||
|
this.projectedPath += cumulativePoint
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_setDisplayedMonths: function () {
|
_setDisplayedMonths: function () {
|
||||||
@ -43,22 +94,43 @@ export default {
|
|||||||
const monthsForward = this.numMonths - this.focusedMonthPosition - 1
|
const monthsForward = this.numMonths - this.focusedMonthPosition - 1
|
||||||
const start = new Date(year, month - 1 - monthsBack)
|
const start = new Date(year, month - 1 - monthsBack)
|
||||||
|
|
||||||
|
let previousAmount = 0
|
||||||
|
|
||||||
for (let i = 0; i < this.numMonths; i++) {
|
for (let i = 0; i < this.numMonths; i++) {
|
||||||
const date = new Date(start.getFullYear(), start.getMonth() + i)
|
const date = new Date(start.getFullYear(), start.getMonth() + i)
|
||||||
const index = format(date, 'MM/YYYY')
|
const index = format(date, 'MM/YYYY')
|
||||||
|
const budget = this.months[index] || null
|
||||||
|
const spendAmount = budget ? budget.spend || previousAmount : 0
|
||||||
|
const cumulativeAmount = budget ? budget.cumulative || budget.projected : 0
|
||||||
|
previousAmount = spendAmount
|
||||||
|
|
||||||
monthsRange.push({
|
monthsRange.push({
|
||||||
|
budget,
|
||||||
|
spendAmount: formatDollars(spendAmount),
|
||||||
|
abbreviatedSpend: abbreviateDollars(spendAmount),
|
||||||
|
cumulativeAmount: formatDollars(cumulativeAmount),
|
||||||
|
abbreviatedCumulative: abbreviateDollars(cumulativeAmount),
|
||||||
date: {
|
date: {
|
||||||
|
monthIndex: format(date, 'M'),
|
||||||
month: format(date, 'MMM'),
|
month: format(date, 'MMM'),
|
||||||
year: format(date,'YYYY')
|
year: format(date,'YYYY')
|
||||||
},
|
},
|
||||||
budget: this.months[index] || null,
|
|
||||||
isHighlighted: this.currentMonth === index,
|
isHighlighted: this.currentMonth === index,
|
||||||
metrics: {
|
metrics: {
|
||||||
x: 0,
|
blockWidth: 0,
|
||||||
width: 0
|
blockX: 0,
|
||||||
|
barHeight: 0,
|
||||||
|
barWidth: 0,
|
||||||
|
barX: 0,
|
||||||
|
barY: 0,
|
||||||
|
cumulativeY: 0,
|
||||||
|
cumulativeX: 0,
|
||||||
|
cumulativeR: 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
console.log(monthsRange)
|
||||||
this.displayedMonths = monthsRange
|
this.displayedMonths = monthsRange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user