91 lines
2.2 KiB
TypeScript
91 lines
2.2 KiB
TypeScript
import { h, type FunctionComponent } from 'preact'
|
|
import { useEffect, useRef } from 'preact/hooks'
|
|
import * as d3 from 'd3'
|
|
import rek from 'rek'
|
|
import Head from './head.ts'
|
|
import usePromise from '../../shared/hooks/use_promise.ts'
|
|
|
|
type AccountPageProps = {
|
|
number: number
|
|
}
|
|
|
|
function empty(element: HTMLElement) {
|
|
while (element.lastElementChild) {
|
|
element.removeChild(element.lastElementChild)
|
|
}
|
|
}
|
|
|
|
const AccountPage: FunctionComponent<AccountPageProps> = ({ number }) => {
|
|
const graphRef = useRef<HTMLDivElement>(null)
|
|
const sums = usePromise<{ month: string; totalAmount: number }[]>(() => rek(`/api/accounts/month-sum/${number}`))
|
|
|
|
useEffect(() => {
|
|
empty(graphRef.current!)
|
|
|
|
const width = 1000
|
|
const height = 1000
|
|
const margin = { left: 50, bottom: 40 }
|
|
const stageWidth = 1000 - margin.left
|
|
const stageHeight = 1000 - margin.bottom
|
|
|
|
const svg = d3
|
|
.select(graphRef.current)
|
|
.append('svg')
|
|
.attr('width', width)
|
|
.attr('height', height)
|
|
.append('g')
|
|
.attr('transform', `translate(${margin.left}, 0)`)
|
|
|
|
const x = d3.scaleBand(
|
|
sums.map(({ month }) => month),
|
|
[0, stageWidth],
|
|
)
|
|
|
|
svg.append('g').attr('transform', `translate(0, ${stageHeight})`).call(d3.axisBottom(x))
|
|
|
|
const y = d3.scaleLinear([0, d3.max(sums, (d) => Math.abs(d.totalAmount))], [stageHeight, 0])
|
|
|
|
svg.append('g').call(d3.axisLeft(y))
|
|
svg
|
|
.append('path')
|
|
.datum(sums)
|
|
.attr('fill', 'none')
|
|
.attr('stroke', 'steelblue')
|
|
.attr('stroke-width', 1.5)
|
|
.attr(
|
|
'd',
|
|
d3
|
|
.line()
|
|
.x((d) => x(d.month))
|
|
.y((d) => y(Math.abs(d.totalAmount))),
|
|
)
|
|
}, [])
|
|
|
|
return (
|
|
<section>
|
|
<Head>
|
|
<title> : Konto</title>
|
|
</Head>
|
|
|
|
<h1>Konto {number}</h1>
|
|
<div ref={graphRef} />
|
|
<table className='grid'>
|
|
<thead>
|
|
<th>Månad</th>
|
|
<th>Summa</th>
|
|
</thead>
|
|
<tbody>
|
|
{sums.map((sum) => (
|
|
<tr>
|
|
<td>{sum.month}</td>
|
|
<td>{sum.totalAmount}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
)
|
|
}
|
|
|
|
export default AccountPage
|