first commt

This commit is contained in:
Romulus21
2023-09-10 08:49:10 +02:00
commit 2dab3b48e1
134 changed files with 16163 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
import React, {Dispatch, FC, FormEvent, SetStateAction, useState} from "react"
import useAxiosTools from "../../hooks/AxiosTools";
import Field from "../Field";
const AddRainfall: FC<AddRainfallProps> = ({reload}) => {
const {axiosPost} = useAxiosTools()
const [date, setDate] = useState((new Date()).toSQLDate())
const [value, setValue] = useState(0)
const handleSubmit = async (event: FormEvent) => {
event.preventDefault()
try {
await axiosPost('/api/rainfalls', {date, value})
setDate((new Date()).toSQLDate())
setValue(0)
reload(new Date())
} catch (e) {
console.error(e)
}
}
return <form onSubmit={handleSubmit}>
<h2>Ajout d'une mesure</h2>
<Field type="date"
name="date"
placeholder="Email"
value={date}
onChange={event => setDate(event.target.value)}
autoFocus>Date</Field>
<Field type="number"
name="value"
placeholder="10"
value={value}
onChange={event => setValue(Number(event.target.value))}>Mesure</Field>
<button type="submit" className="mt-3 w-full bg-blue-700 rounded">Valider</button>
</form>
}
export default AddRainfall
interface AddRainfallProps {
reload: Dispatch<SetStateAction<Date>>
}

View File

@@ -0,0 +1,44 @@
import React, {FC, useEffect, useState} from "react"
import useAxiosTools from "../../hooks/AxiosTools";
import {rainfall} from "../../types";
import {AxiosError} from "axios";
const LastFiveMesure: FC<LastFiveMesureProps> = ({loadedAt}) => {
const {error, setError, axiosGet} = useAxiosTools()
const [data, setData] = useState<rainfall[]>([])
useEffect(() => {
fetchData()
}, [loadedAt])
const fetchData = async () => {
try {
const res = await axiosGet('/api/rainfalls/last')
setData(res.data)
} catch (e) {
if (e instanceof AxiosError) {
setError(e.message)
} else {
console.error(e)
}
}
}
return <div>
<h1>5 dernières mesures</h1>
{error && <div>{error}</div>}
<ul>
{data.map(line => <li key={line.id} className="w-36 flex justify-between">
<span>{(new Date(line.date)).toLocaleDateString()}</span>
<span>{line.value}</span>
</li>)}
</ul>
</div>
}
export default LastFiveMesure
interface LastFiveMesureProps {
loadedAt: Date,
}

View File

@@ -0,0 +1,100 @@
import * as d3 from "d3"
import React, {FC, LegacyRef, useEffect, useRef} from "react"
import {rainfall} from "../../types";
const RainfallGraph: FC<RainfallGraphProps> = ({width, height, data, start_date, end_date}) => {
const svgRef = useRef<SVGSVGElement|null>(null)
useEffect(() => {
renderSVG()
}, [width, height, data])
const renderSVG = () => {
const margin = {top: 10, right: 30, bottom: 30, left: 20}
const gWidth = width - margin.left - margin.right
const gHeight = height - margin.top - margin.bottom
console.log('data', data)
d3.select(svgRef.current).selectAll("*").remove()
const svg = d3.select(svgRef.current)
.attr('width', gWidth + margin.left + margin.right)
.attr('height', gHeight + margin.top + margin.bottom)
.attr('class', 'relative')
.append('g')
.attr('transform', "translate(" + margin.left + "," + margin.top + ")")
const yMax = data.reduce((result, item) => item.value > result ? item.value : result, 0)
const y = d3.scaleLinear()
.domain([0, yMax + 10])
.range([gHeight, 0])
const x = d3.scaleUtc()
.domain([(new Date(start_date)), (new Date(end_date))])
.range([margin.left, width - margin.right])
const yAxis = svg.append('g')
.attr('transform', `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(height / 80))
.call(g => g.select('.domain').remove())
.call(g => g.append('text')
.attr('x', -margin.left)
.attr('y', 10)
.attr('fill', 'currentColor')
.attr('text-anchor', 'start')
)
svg.append("g")
.attr("transform", "translate(0," + gHeight + ")")
.call(d3.axisBottom(x)
.tickFormat(
// @ts-ignore
d3.timeFormat("%d/%m/%Y")
)
, 0)
if (data.length === 0) {
// no values text
const titleBox = svg.append("g")
.attr("x", (width))
.attr("y", height)
titleBox.append("text")
.attr("x", (width / 2))
.attr("y", height / 2)
.attr("text-anchor", "middle")
.style("font-size", "20px")
.text('Aucune Donnée')
} else {
yAxis.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - margin.left - margin.right)
.attr("stroke-opacity", 0.1))
}
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("fill", "steelblue")
.attr("x", d => x(new Date(d.date)) * (1 - (100 / data.length)/100))
.attr("y", d => y(d.value))
.attr("width", (width - 44 + ((width - 44) / (data.length + 1))) / (data.length + 1) - 2)
.attr("height", d => height - margin.bottom - 10 - y(d.value))
.append('title')
.text(d => `${(new Date(d.date)).toLocaleDateString()} : ${d.value}`)
}
return <svg ref={svgRef} />
}
export default RainfallGraph
interface RainfallGraphProps {
width: number,
height: number,
data: rainfall[],
start_date: string,
end_date: string,
}