diff options
author | Galen Guyer <galen@galenguyer.com> | 2021-10-29 12:19:15 -0400 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2021-10-29 12:19:15 -0400 |
commit | 0216f8879440ce73d90a9e58cc5eac68240e9fdd (patch) | |
tree | 6a1ed3c5c9a4c9bc26ae1862ff6e13b1f7105643 /src |
add static data for 2020-2021 school year
Diffstat (limited to 'src')
-rw-r--r-- | src/App.css | 15 | ||||
-rw-r--r-- | src/App.js | 215 | ||||
-rw-r--r-- | src/App.test.js | 8 | ||||
-rw-r--r-- | src/Card.css | 10 | ||||
-rw-r--r-- | src/Card.js | 25 | ||||
-rw-r--r-- | src/GoatCounter.js | 26 | ||||
-rw-r--r-- | src/History.js | 82 | ||||
-rw-r--r-- | src/HistoryTable.js | 40 | ||||
-rw-r--r-- | src/MainPage.js | 126 | ||||
-rw-r--r-- | src/index.css | 15 | ||||
-rw-r--r-- | src/index.js | 22 | ||||
-rw-r--r-- | src/logo.svg | 7 | ||||
-rw-r--r-- | src/reportWebVitals.js | 13 | ||||
-rw-r--r-- | src/setupTests.js | 5 |
14 files changed, 609 insertions, 0 deletions
diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..78106d4 --- /dev/null +++ b/src/App.css @@ -0,0 +1,15 @@ +.App { + text-align: center; + padding-bottom: 2rem; + padding-top: 1rem; + width: 90%; + margin-left: auto; + margin-right: auto; +} + +.Section { + display: flex; + justify-content: center; + margin-left: auto; + margin-right: auto; +} diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..fd5e6d0 --- /dev/null +++ b/src/App.js @@ -0,0 +1,215 @@ +import React from "react"; +import useSWR from "swr"; +import { DateTime } from "luxon"; +import { BrowserRouter, Route, Switch, Link } from "react-router-dom"; +import MainPage from "./MainPage"; +import History from "./History"; +import HistoryTable from "./HistoryTable"; +import "./App.css"; + +const url = "/data.json"; + +function App() { + let { data: rawData, error: error } = useSWR(url); + + const [timeDifference, setTimeDifference] = React.useState(1); + const [showAllTime, setShowAllTime] = React.useState(false); + + if (error) + return ( + <div className="App"> + <h1>RIT Covid Dashboard</h1> + <h2>An error occurred</h2> + </div> + ); + if (!rawData) + return ( + <div className="App"> + <h1>RIT Covid Dashboard</h1> + <h2>Loading latest data...</h2> + </div> + ); + + // rawData = rawData.slice(0, 177); + let data = rawData; + console.log(data.length); + const local = DateTime.local().zoneName; + const semesterStart = DateTime.fromISO("2021-01-01"); + // if (!showAllTime) { + // data = rawData.filter((d) => { + // let date = DateTime.fromSQL(d.last_updated, { zone: "UTC" }).setZone(local); + // return date > semesterStart; + // }); + // const last = rawData[rawData.length - data.length - 1]; + // data = data.map((d) => { + // return { + // alert_level: d.alert_level, + // beds_available: d.beds_available, + // isolation_off_campus: d.isolation_off_campus, + // isolation_on_campus: d.isolation_on_campus, + // last_updated: d.last_updated, + // new_staff: d.new_staff, + // new_students: d.new_students, + // quarantine_off_campus: d.quarantine_off_campus, + // quarantine_on_campus: d.quarantine_on_campus, + // tests_administered: d.tests_administered - last.tests_administered, + // total_staff: d.total_staff - last.total_staff, + // total_students: d.total_students - last.total_students, + // }; + // }); + // } + + const latest = data[data.length - 1]; + const prior = data[data.length - (1 + timeDifference)]; + return ( + <BrowserRouter> + <div className="App"> + <h1 className="text-4xl"> + <Link to="/">RIT Covid Dashboard</Link> + </h1> + {/* + <h3> + Last Updated:{" "} + {lastUpdate.toLocaleString({ + weekday: "long", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + })} + </h3> + <h4 className="text-sm text-gray-600"> + Prior Update:{" "} + {priorUpdate.toLocaleString({ + weekday: "long", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + })}{" "} + ({timeDifference == 1 ? "one day ago" : timeDifference == 5 ? "one week ago" : "two weeks ago"}) + </h4> + */} + {/* <button + onClick={() => setTimeDifference(timeDifference == 1 ? 5 : timeDifference == 5 ? 10 : 1)} + className="bg-transparent text-sm hover:bg-orange-400 text-gray-600 hover:text-white py-1 my-1 px-2 border border-orange-300 hover:border-transparent rounded transition ease-in-out duration-300" + > + Use {timeDifference == 10 ? "one day" : timeDifference == 5 ? "two weeks" : "one week"} ago + </button> + + <button + onClick={() => setShowAllTime(showAllTime ? false : true)} + className="bg-transparent text-sm hover:bg-orange-400 text-gray-600 hover:text-white py-1 my-1 px-2 border border-orange-300 hover:border-transparent rounded transition ease-in-out duration-300" + > + Show {showAllTime ? "current semester" : "all time"} + </button> */} + <br /> + <Switch> + <Route exact path="/"> + <MainPage data={data} timeDifference={timeDifference} showAllTime={showAllTime} /> + </Route> + <Route path="/totalstudents"> + <History + name="Total Student Cases" + data={data.map((d) => { + return { value: d.total_students, date: d.last_updated }; + })} + /> + </Route> + <Route path="/totalstaff"> + <History + name="Total Staff Cases" + data={data.map((d) => { + return { value: d.total_staff, date: d.last_updated }; + })} + /> + </Route> + <Route path="/newstudents"> + <History + name="New Student Cases" + data={data.map((d) => { + return { value: d.new_students, date: d.last_updated }; + })} + /> + </Route> + <Route path="/newstaff"> + <History + name="New Staff Cases" + data={data.map((d) => { + return { value: d.new_staff, date: d.last_updated }; + })} + /> + </Route> + <Route path="/quarantineoncampus"> + <History + name="Quarantine On Campus" + data={data.map((d) => { + return { value: d.quarantine_on_campus, date: d.last_updated }; + })} + /> + </Route> + <Route path="/quarantineoffcampus"> + <History + name="Quarantine Off Campus" + data={data.map((d) => { + return { value: d.quarantine_off_campus, date: d.last_updated }; + })} + /> + </Route> + + <Route path="/isolationoncampus"> + <History + name="Isolation On Campus" + data={data.map((d) => { + return { value: d.isolation_on_campus, date: d.last_updated }; + })} + /> + </Route> + <Route path="/isolationoffcampus"> + <History + name="Isolation Off Campus" + data={data.map((d) => { + return { value: d.isolation_off_campus, date: d.last_updated }; + })} + /> + </Route> + <Route path="/tests"> + <History + name="Tests Administered" + data={data.map((d) => { + return { value: d.tests_administered, date: d.last_updated }; + })} + /> + </Route> + <Route path="/beds"> + <History + name="Bed Availability" + data={data.map((d) => { + return { value: d.beds_available, date: d.last_updated }; + })} + /> + </Route> + </Switch> + <br /> + <p> + By Galen Guyer. Source available on{" "} + <a className="text-blue-700" href="https://github.com/galenguyer/rit-covid-dashboard"> + GitHub + </a>{" "} + ( + <a className="text-blue-700" href="https://github.com/galenguyer/rit-covid-dashboard/issues"> + Report Issue + </a> + ) + </p> + <p> + <a className="text-blue-700" href="https://galenguyer.com/projects/ritcoviddashboard"> + API Documentation + </a> + </p> + </div> + </BrowserRouter> + ); +} + +export default App; diff --git a/src/App.test.js b/src/App.test.js new file mode 100644 index 0000000..7c46384 --- /dev/null +++ b/src/App.test.js @@ -0,0 +1,8 @@ +import { render, screen } from "@testing-library/react"; +import App from "./App"; + +test("renders learn react link", () => { + render(<App />); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/src/Card.css b/src/Card.css new file mode 100644 index 0000000..785b3e5 --- /dev/null +++ b/src/Card.css @@ -0,0 +1,10 @@ +.Card { + padding: 16px; + width: 40%; +} + +@media screen and (min-width: 768px) { + .Card { + width: 20%; + } +} diff --git a/src/Card.js b/src/Card.js new file mode 100644 index 0000000..a58f611 --- /dev/null +++ b/src/Card.js @@ -0,0 +1,25 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import "./Card.css"; + +const Card = (props) => { + let diff = props.diff.toString(); + if (diff.charAt(0) != "-") { + diff = "+" + diff; + } + + return ( + <Link className="Card" style={{ padding: 0 }} to={props.link}> + <div className="group bg-white hover:bg-orange-400 rounded-lg border-2 border-orange-300 hover:border-orange-400 p-2 m-6 transition ease-in-out duration-300"> + <p> + <span className="text-2xl group-hover:text-white transition ease-in-out duration-300"> + {props.latest}{" "} + </span> + </p> + <h3 className="text-base group-hover:text-white transition ease-in-out duration-300">{props.name}</h3> + </div> + </Link> + ); +}; + +export default Card; diff --git a/src/GoatCounter.js b/src/GoatCounter.js new file mode 100644 index 0000000..07a768a --- /dev/null +++ b/src/GoatCounter.js @@ -0,0 +1,26 @@ +import React from "react"; + +class GoatCounter extends React.Component { + componentDidMount() { + window.counter = "https://rcd.goatcounter.com/count"; + const script = window.document.createElement("script"); + script.async = 1; + script.src = "https://gc.zgo.at/count.js"; + script.id = "goatcounter"; + script.setAttribute("data-goatcounter", "https://rcd.goatcounter.com/count"); + (window.document.head || window.document.body).appendChild(script); + } + + componentWillUnmount() { + const script = window.document.getElementById("goatcounter"); + if (script) { + script.parentNode.removeChild(script); + } + } + + render() { + return null; + } +} + +export default GoatCounter; diff --git a/src/History.js b/src/History.js new file mode 100644 index 0000000..7425b61 --- /dev/null +++ b/src/History.js @@ -0,0 +1,82 @@ +import { React, PureComponent } from "react"; +import { DateTime } from "luxon"; +import { + BarChart, + Bar, + LineChart, + Line, + CartesianGrid, + XAxis, + YAxis, + Tooltip, + ResponsiveContainer, + Label, +} from "recharts"; +import GoatCounter from "./GoatCounter"; + +const History = (props) => { + const offset = DateTime.fromSQL(props.data[0].date, { zone: "UTC" }).setZone(DateTime.local().zoneName).toSeconds(); + const data = props.data.map((d) => { + return { + value: d.value, + date: DateTime.fromSQL(d.date, { zone: "UTC" }).setZone(DateTime.local().zoneName).toSeconds(), + }; + }); + + return ( + <> + <h3 className="text-3xl">{props.name}</h3> + <LineChart + style={{ marginLeft: "auto", marginRight: "auto" }} + width={730} + height={500} + margin={{ top: 15, right: 30, left: 20, bottom: 5 }} + data={data} + > + <Line type="monotone" dataKey="value" stroke="#CD8508" dot={false} /> + <CartesianGrid strokeDasharray="3 3" /> + <XAxis + dataKey="date" + type="number" + tickCount={14} + domain={["dataMin", "dataMax"]} + tick={<CustomizedAxisTick />} + height={90} + /> + <YAxis dataKey="value" type="number"></YAxis> + <Tooltip content={CustomTooltip} /> + </LineChart> + <GoatCounter /> + </> + ); +}; + +class CustomizedAxisTick extends PureComponent { + render() { + const { x, y, payload } = this.props; + + return ( + <g transform={`translate(${x},${y})`}> + <text className="Graph-Label" x={0} y={0} dy={16} textAnchor="end" fill="#666" transform="rotate(-40)"> + {DateTime.fromSeconds(payload.value).toLocaleString()} + </text> + </g> + ); + } +} + +const CustomTooltip = ({ active, payload, label }) => { + if (active) { + return ( + <div className="custom-tooltip bg-white border-orange-300 border-2 rounded-lg p-2"> + <p className="label"> + {DateTime.fromSeconds(label).toLocaleString({ weekday: "long", month: "long", day: "2-digit" })} + </p> + <p className="desc">{payload[0].value}</p> + </div> + ); + } + return null; +}; + +export default History; diff --git a/src/HistoryTable.js b/src/HistoryTable.js new file mode 100644 index 0000000..fb27f0e --- /dev/null +++ b/src/HistoryTable.js @@ -0,0 +1,40 @@ +import { React } from "react"; +import { DateTime } from "luxon"; +import GoatCounter from "./GoatCounter"; + +const HistoryTable = (props) => { + const data = props.data; + console.log(data); + let table = ( + <table className="table-auto" style={{ marginLeft: "auto", marginRight: "auto" }}> + <tbody> + <tr> + <td className="border py-2 px-4">Date</td> + <td className="border py-2 px-4">Positive Case Rate</td> + </tr> + {data.map((element) => { + return ( + <tr> + <td className="border px-4" py-2> + {DateTime.fromSQL(element.date, { zone: "UTC" }) + .setZone(DateTime.local().zoneName) + .toLocaleString({ weekday: "long", month: "long", day: "2-digit" })} + </td> + <td className="border px-4 py-2">{element.value}%</td> + </tr> + ); + })} + </tbody> + </table> + ); + + return ( + <> + <h3 className="text-3xl">{props.name}</h3> + {table} + <GoatCounter /> + </> + ); +}; + +export default HistoryTable; diff --git a/src/MainPage.js b/src/MainPage.js new file mode 100644 index 0000000..fcc2e0b --- /dev/null +++ b/src/MainPage.js @@ -0,0 +1,126 @@ +import React from "react"; +import Card from "./Card"; +import GoatCounter from "./GoatCounter"; + +const MainPage = (props) => { + const data = props.data; + const latest = data[data.length - 1]; + const prior = data[data.length - (1 + props.timeDifference)]; + + return ( + <> + <h2 className="text-xl"> + This site shows data from the 2020 Fall and 2021 Spring semesters. + </h2> + <br /> + <div id="total"> + <h4 className="text-2xl"> + Total Positive Cases Since August 19 (First Day of Classes) + </h4> + <div className="Section"> + <Card + name="Students" + latest={latest.total_students} + diff={latest.total_students - prior.total_students} + link="/totalstudents" + /> + <Card + name="Staff" + latest={latest.total_staff} + diff={latest.total_staff - prior.total_staff} + link="/totalstaff" + /> + </div> + </div> + <br /> + <div id="new"> + <h4 className="text-2xl">New Positive Cases From Past 14 Days</h4> + <div className="Section"> + <Card + name="Students" + latest={latest.new_students} + diff={latest.new_students - prior.new_students} + link="/newstudents" + /> + <Card + name="Staff" + latest={latest.new_staff} + diff={latest.new_staff - prior.new_staff} + link="/newstaff" + /> + </div> + </div> + <br /> + <div id="quarantine"> + <h4 className="text-2xl">Number of Students in Quarantine</h4> + <h5 className="text-base"> + Quarantine separates and restricts the movement of people who were exposed to a contagious disease + to see if they become sick. + </h5> + <div className="Section"> + <Card + name="On Campus" + latest={latest.quarantine_on_campus} + diff={latest.quarantine_on_campus - prior.quarantine_on_campus} + link="/quarantineoncampus" + /> + <Card + name="Off Campus" + latest={latest.quarantine_off_campus} + diff={latest.quarantine_off_campus - prior.quarantine_off_campus} + link="/quarantineoffcampus" + /> + </div> + </div> + <br /> + <div id="isolation"> + <h4 className="text-2xl">Number of Students in Isolation</h4> + <h5 className="text-base"> + Isolation separates sick people with a contagious disease from people who are not sick. + </h5> + <div className="Section"> + <Card + name="On Campus" + latest={latest.isolation_on_campus} + diff={latest.isolation_on_campus - prior.isolation_on_campus} + link="isolationoncampus" + /> + <Card + name="Off Campus" + latest={latest.isolation_off_campus} + diff={latest.isolation_off_campus - prior.isolation_off_campus} + link="isolationoffcampus" + /> + </div> + </div> + <br /> + <div id="tests"> + <h4 className="text-2xl">Tests</h4> + <div className="Section"> + <Card + name="Tests Administered" + latest={latest.tests_administered} + diff={latest.tests_administered - prior.tests_administered} + link="/tests" + /> + </div> + </div> + <br /> + <div id="beds"> + <h4 className="text-2xl">Quarantine/Isolation Bed Availability On-campus</h4> + <div className="Section"> + <Card + name="Beds Available" + latest={latest.beds_available + "%"} + diff={latest.beds_available - prior.beds_available + "%"} + suffix="%" + link="/beds" + /> + </div> + </div> + <GoatCounter /> + </> + ); +}; + +export default MainPage; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..868b6c6 --- /dev/null +++ b/src/index.css @@ -0,0 +1,15 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +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/src/index.js b/src/index.js new file mode 100644 index 0000000..4c1dc74 --- /dev/null +++ b/src/index.js @@ -0,0 +1,22 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import { SWRConfig } from "swr"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; + +const fetcher = (...args) => fetch(...args).then((res) => res.json()); + +ReactDOM.render( + <React.StrictMode> + <SWRConfig value={{ fetcher }}> + <App /> + </SWRConfig> + </React.StrictMode>, + 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/src/logo.svg b/src/logo.svg new file mode 100644 index 0000000..6b60c10 --- /dev/null +++ b/src/logo.svg @@ -0,0 +1,7 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"> + <g fill="#61DAFB"> + <path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/> + <circle cx="420.9" cy="296.5" r="45.7"/> + <path d="M520.5 78.1z"/> + </g> +</svg> diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js new file mode 100644 index 0000000..7dc6b90 --- /dev/null +++ b/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/src/setupTests.js b/src/setupTests.js new file mode 100644 index 0000000..1dd407a --- /dev/null +++ b/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"; |