AnimateHeight for Info, error handling for the Osu Info (#4)

This commit is contained in:
Taevas 2024-05-01 19:12:02 +02:00
parent cca62c093f
commit dad037bed0
5 changed files with 88 additions and 82 deletions

View file

@ -13,19 +13,11 @@ const handler: Handler = async () => {
}, },
}); });
if (gitlab.status !== 200) {
return {
statusCode: 404,
body: "",
};
}
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
const {created_at} = (await gitlab.json() as Record<string, any>)[0]; const {created_at} = (await gitlab.json() as Record<string, any>)[0];
if (typeof created_at !== "string") { if (typeof created_at !== "string") {
return { return {
statusCode: 404, statusCode: 404,
body: "",
}; };
} }

View file

@ -20,24 +20,22 @@ const handler: Handler = async () => {
}), }),
]) as osu.User.Extended[]; ]) as osu.User.Extended[];
void api.revokeToken();
const info: OsuInfo = { const info: OsuInfo = {
country: (profile[0]).country.name || "Unknown", country: (profile[0]).country.name ?? "Unknown",
osu: {global: 0, country: 0},
taiko: {global: 0, country: 0},
fruits: {global: 0, country: 0},
mania: {global: 0, country: 0},
}; };
for (const ruleset of profile) { for (const ruleset of profile) {
if (ruleset.rank_history) { if (ruleset.rank_history) {
const stats = ruleset.statistics; const stats = ruleset.statistics;
info[ruleset.rank_history.mode].global = stats.global_rank ?? 0; info[ruleset.rank_history.mode] = {
info[ruleset.rank_history.mode].country = stats.country_rank ?? 0; global: stats.global_rank ?? 0,
country: stats.country_rank ?? 0,
};
} }
} }
void api.revokeToken();
return { return {
statusCode: 200, statusCode: 200,
body: JSON.stringify(info), body: JSON.stringify(info),

View file

@ -1,4 +1,5 @@
import React from "react"; import React, {useState} from "react";
import AnimateHeight, {type Height} from "react-animate-height";
export default function Info({ export default function Info({
type, type,
@ -13,9 +14,21 @@ export default function Info({
}>; }>;
error?: boolean; error?: boolean;
}) { }) {
const sections = websites.map((w) => { const [height, setHeight] = useState<Height>(0);
const sections = websites.map((w, i) => {
setTimeout(() => { // somehow necessary to not always rerender
setHeight("auto");
}, 0);
return ( return (
<div key={w.name} id={w.name.toLowerCase().match(/[a-z]/g)!.join().replace(/,/g, "")}> <AnimateHeight
key={w.name}
id={w.name.toLowerCase().match(/[a-z]/g)!.join().replace(/,/g, "")}
delay={150 * i}
duration={150 * (i + 1)}
height={height}
>
<a href={w.link} target="_blank" rel="noreferrer"> <a href={w.link} target="_blank" rel="noreferrer">
<h2 className="uppercase text-right font-bold pr-1 bg-white text-red-500"> <h2 className="uppercase text-right font-bold pr-1 bg-white text-red-500">
{w.name} {w.name}
@ -24,7 +37,7 @@ export default function Info({
<div className="info p-3 m-auto"> <div className="info p-3 m-auto">
{w.elements} {w.elements}
</div> </div>
</div> </AnimateHeight>
); );
}); });

View file

@ -4,80 +4,83 @@ import "../../style/infos/osu.css";
export type OsuInfo = { export type OsuInfo = {
country: string; country: string;
osu: {global: number; country: number}; osu?: {global: number; country: number};
taiko: {global: number; country: number}; taiko?: {global: number; country: number};
fruits: {global: number; country: number}; fruits?: {global: number; country: number};
mania: {global: number; country: number}; mania?: {global: number; country: number};
} | undefined; };
export default function Osu() { export default function Osu() {
const [osu, setOsu]: [OsuInfo, React.Dispatch<React.SetStateAction<OsuInfo>>] = useState(); const [osu, setOsu]: [OsuInfo, React.Dispatch<React.SetStateAction<OsuInfo>>] = useState({country: "Unknown"});
const [error, setError] = useState(false);
const getOsu = async () => { const getOsu = async () => {
const response = await fetch("/.netlify/functions/osu").then(async r => r.json());
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
setOsu(response); setOsu(await fetch("/.netlify/functions/osu").then(async r => r.json()));
}; };
useEffect(() => { useEffect(() => {
void getOsu(); getOsu().catch(() => {
setError(true);
});
}, []); }, []);
if (osu === undefined) {
return <></>; const generateWebsite = (name: string, interalName: string, data: {global: number; country: number} | undefined) => {
const website = {
name,
link: `https://osu.ppy.sh/users/7276846/${interalName}`,
elements: [] as React.JSX.Element[],
};
if (data) {
website.elements.push(
<div key={interalName} className="flex">
<img className="m-auto w-16 h-16" alt={`${name} mode logo`} src={`/mode-${interalName}.png`} />
<div className="m-auto">
<p>Global: <strong>#{data.global}</strong></p>
<p>{osu.country}: <strong>#{data.country}</strong></p>
</div>
</div>,
);
}
return website;
};
const osuWebsite = generateWebsite("osu!", "osu", osu.osu);
const taikoWebsite = generateWebsite("osu!taiko", "taiko", osu.taiko);
const catchWebsite = generateWebsite("osu!catch", "fruits", osu.fruits);
const maniaWebsite = generateWebsite("osu!mania", "mania", osu.mania);
const websites = [
osuWebsite,
taikoWebsite,
catchWebsite,
maniaWebsite,
];
for (const website of websites) {
if (!website.elements.length) {
return (
<Info
type="Rhythm games"
websites={[]}
error={error}
/>
);
}
} }
return ( return (
<Info <Info
type="Rhythm games" type="Rhythm games"
websites={[{ websites={[
name: "osu!", osuWebsite,
link: "https://osu.ppy.sh/users/7276846/osu", taikoWebsite,
elements: [ catchWebsite,
<div key={"osu"} className="flex"> maniaWebsite,
<img className="m-auto w-16 h-16" alt="osu mode logo" src="/mode-osu.png" /> ]}
<div className="m-auto">
<p>Global: <strong>#{osu.osu.global}</strong></p>
<p>{osu.country}: <strong>#{osu.osu.country}</strong></p>
</div>
</div>,
],
}, {
name: "osu!taiko",
link: "https://osu.ppy.sh/users/7276846/taiko",
elements: [
<div key={"osu!taiko"} className="flex">
<img className="m-auto w-16 h-16" alt="taiko mode logo" src="/mode-taiko.png" />
<div className="m-auto">
<p>Global: <strong>#{osu.taiko.global}</strong></p>
<p>{osu.country}: <strong>#{osu.taiko.country}</strong></p>
</div>
</div>,
],
}, {
name: "osu!catch",
link: "https://osu.ppy.sh/users/7276846/fruits",
elements: [
<div key={"osu!catch"} className="flex">
<img className="m-auto w-16 h-16" alt="ctb mode logo" src="/mode-fruits.png" />
<div className="m-auto">
<p>Global: <strong>#{osu.fruits.global}</strong></p>
<p>{osu.country}: <strong>#{osu.fruits.country}</strong></p>
</div>
</div>,
],
}, {
name: "osu!mania",
link: "https://osu.ppy.sh/users/7276846/mania",
elements: [
<div key={"osu!mania"} className="flex">
<img className="m-auto w-16 h-16" alt="mania mode logo" src="/mode-mania.png" />
<div className="m-auto">
<p>Global: <strong>#{osu.mania.global}</strong></p>
<p>{osu.country}: <strong>#{osu.mania.country}</strong></p>
</div>
</div>,
],
}]}
/> />
); );
} }

View file

@ -12,7 +12,7 @@ function Infos() {
<div id="infos" className="hidden lg:inline-block text-white static m-auto lg:bg-gradient-to-r from-sky-600 to-indigo-600 <div id="infos" className="hidden lg:inline-block text-white static m-auto lg:bg-gradient-to-r from-sky-600 to-indigo-600
border-solid border-white lg:border-l-3 h-screen lg:fixed lg:right-0 lg:overflow-y-auto"> border-solid border-white lg:border-l-3 h-screen lg:fixed lg:right-0 lg:overflow-y-auto">
<Lastfm/> <Lastfm/>
{/* <Git/> */} <Git/>
<Speedruncom/> <Speedruncom/>
<Anilist/> <Anilist/>
<Wanikani/> <Wanikani/>