Add the Umami script and the Website Info (#10)

Rather barebones for now because I can go several ways from there
This commit is contained in:
Taevas 2025-02-19 14:59:58 +01:00
parent 48051690a3
commit d42bb932cd
7 changed files with 100 additions and 0 deletions

View file

@ -28,4 +28,5 @@ This package makes use of several online APIs through Netlify in order to delive
- `API_LASTFM`
- `API_OSU`
- `API_WANIKANI`
- `API_UMAMI`
- `URL_MONGODB`

BIN
bun.lockb

Binary file not shown.

View file

@ -7,6 +7,7 @@
content="width=device-width, initial-scale=1, maximum-scale=1"
/>
<link rel="stylesheet" href="/src/App.css">
<script defer src="https://cloud.umami.is/script.js" data-website-id="3461d539-c2fb-4930-9d4a-a0e4016a174a"></script>
<title>Site - taevas.xyz</title>
</head>
<body class="bg-gradient-to-tl from-indigo-100 via-sky-300 to-indigo-100 bg-fixed">

View file

@ -0,0 +1,44 @@
import { UmamiInfo } from "#Infos/Website/Umami.js";
import {type Handler} from "@netlify/functions";
const handler: Handler = async () => {
const api_server = "https://api.umami.is/v1";
const website_id = "3461d539-c2fb-4930-9d4a-a0e4016a174a";
const now = new Date();
const response = await fetch(`${api_server}/websites/${website_id}/stats?startAt=${Number(new Date("2025"))}&endAt=${Number(now)}`, {
headers: {
"Accept": "application/json",
"x-umami-api-key": process.env.API_UMAMI!
},
});
// From https://github.com/umami-software/api-client/blob/master/src/types.ts
// Not using the package directly because of serious issues I consider it to have
const umami = await response.json() as {
pageviews: { value: number; prev: number };
visitors: { value: number; prev: number };
visits: { value: number; prev: number };
bounces: { value: number; prev: number };
totaltime: { value: number; prev: number };
};
if (!umami) {
return {
statusCode: 404,
};
}
const info: UmamiInfo = {
pageviews: umami.pageviews.value,
visits: umami.visits.value,
visitors: umami.visitors.value,
totaltime: umami.totaltime.value
};
return {
statusCode: 200,
body: JSON.stringify(info),
};
};
export {handler};

View file

@ -0,0 +1,36 @@
import React, {useState, useEffect} from "react";
import Website from "../Website.js";
import DataHandler from "#Infos/DataHandler.js";
export type UmamiInfo = {
pageviews: number
visits: number
visitors: number
totaltime: number
} | undefined;
export default function Umami() {
const {data, error, setError} = DataHandler<UmamiInfo>("/.netlify/functions/umami", 60 * 5);
const [elements, setElements] = useState([] as React.JSX.Element[]);
useEffect(() => {
if (data) {
try {
setElements([
<p className="text-left" key={"info"}><b>My website has been <br/>viewed {data.pageviews} times <br/>by {data.visitors} unique visitors!</b></p>
]);
} catch {
setError(true);
}
}
}, [data]);
return (
<Website
name="Umami"
link="https://cloud.umami.is/share/g31G2F06EWgN9sRM/taevas.xyz"
elements={elements}
error={error}
/>
);
}

View file

@ -0,0 +1,16 @@
import React from "react";
import Info from "../Info.js";
import Umami from "./Umami.js";
export default function Speedrun() {
const umami = <Umami key={"umami"}/>;
return (
<Info
type="Website"
websites={[
umami,
]}
/>
);
}

View file

@ -7,6 +7,7 @@ import RhythmGames from "./RhythmGames/index.js";
import Anime from "./Anime/index.js";
// import Japanese from "./Japanese/index.js";
import Fediverse from "./Fediverse/index.js";
import Website from "./Website/index.js";
export default class Infos extends Component {
private readonly dragbar = React.createRef<HTMLDivElement>();
@ -25,6 +26,7 @@ export default class Infos extends Component {
{/*<Japanese/>*/}
<RhythmGames/>
{/*<Hacking/>*/}
<Website/>
</div>
</div>;
}