diff --git a/frontend/src/App.css b/frontend/src/App.css new file mode 100644 index 0000000..74b5e05 --- /dev/null +++ b/frontend/src/App.css @@ -0,0 +1,38 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/frontend/src/App.js b/frontend/src/App.js new file mode 100644 index 0000000..b7d000b --- /dev/null +++ b/frontend/src/App.js @@ -0,0 +1,114 @@ +import React, { useState, useEffect } from 'react'; +import logo from './logo.svg'; +import './App.css'; + +import { Line, Bar } from "react-chartjs-2"; + +function sec2time(timeInSeconds) { + var pad = function(num, size) { return ('000' + num).slice(size * -1); }, + time = parseFloat(timeInSeconds).toFixed(3), + hours = Math.floor(time / 60 / 60), + minutes = Math.floor(time / 60) % 60, + seconds = Math.floor(time - minutes * 60), + milliseconds = time.slice(-3); + + return pad(hours, 2) + ':' + pad(minutes, 2) + ':' + pad(seconds, 2) + ',' + pad(milliseconds, 3); +} +/* +async function getTestUmsatz() { + const response = await fetch('/api/umsatz', {}); + const json = await response.json(); +// .then(response => response.json()) + // .then(data => console.log(data)); + console.log("get called"); + return json; +} +*/ + +function App() { + const [currentTime, setCurrentTime] = useState(0); + const [umsatzData, setUmsatzData] = useState([]); + const [error, setError] = useState(null); + const [isLoaded, setIsLoaded] = useState(false); + + useEffect(() => { + fetch('/api/umsatz') + .then(response => response.json()) + .then(data => { + setIsLoaded(true); + setUmsatzData(data); + }, + (error) => { + setIsLoaded(true); + setError(error); + }); + fetch('/time') + .then(result => result.json()) + .then(data => { + setCurrentTime(sec2time(data.time)); + }); + }, []); + + //labels werden über die options bereits gesetzt +// var labels = umsatzData.map(element => element.monat); + + var jsonData = { + labels: umsatzData.map(element => element.monat), + datasets: [ + { + data: umsatzData.map(element => element.wert), + fill: true, + backgroundColor: "rgba(75, 192, 192, 0.2)", + borderColor: "rgba(75, 192, 192, 1)" + } + ] + }; + + var options = { + tooltips: { + callbacks: { + label: function(tooltipItems, data) { + return tooltipItems.yLabel.toLocaleString('de') + " €"; + } + } + }, + scales: { + yAxes: [ + { + ticks: { + callback: function(label, index, labels) { + return (label / 1000).toLocaleString('de') + ' k€'; + } + }, + scaleLabel: { + display: true, + labelString: '1k = 1.000' + } + } + ] + } + }; + + //Gelegentlich ist json leer, dann lädt die Seite nicht, + //sofern Fehler nicht abgefangen werden + if (error) { + return
Error: {error.message}
; + } else if (!isLoaded) { + return
Loading...
; + } else { + return ( +
+
+ logo +

The current time is {currentTime}.

+
+ + +
+ ); + } +} + +export default App; diff --git a/frontend/src/index.css b/frontend/src/index.css new file mode 100644 index 0000000..ec2585e --- /dev/null +++ b/frontend/src/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/frontend/src/index.js b/frontend/src/index.js new file mode 100644 index 0000000..ef2edf8 --- /dev/null +++ b/frontend/src/index.js @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +ReactDOM.render( + + + , + document.getElementById('root') +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/frontend/src/logo.svg b/frontend/src/logo.svg new file mode 100644 index 0000000..6b60c10 --- /dev/null +++ b/frontend/src/logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frontend/src/reportWebVitals.js b/frontend/src/reportWebVitals.js new file mode 100644 index 0000000..5253d3a --- /dev/null +++ b/frontend/src/reportWebVitals.js @@ -0,0 +1,13 @@ +const reportWebVitals = onPerfEntry => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/frontend/src/setupTests.js b/frontend/src/setupTests.js new file mode 100644 index 0000000..8f2609b --- /dev/null +++ b/frontend/src/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom';