add some new fun things

This commit is contained in:
2026-01-02 17:07:42 -05:00
parent 937b401b82
commit c67b78a71d
11 changed files with 207 additions and 82 deletions
+2 -2
View File
@@ -2,8 +2,8 @@ import type { ReactNode } from "react";
export default function Layout({ children }: { children: ReactNode }) {
return (
<div className="bg-black text-white min-h-screen flex flex-col items-center sm:justify-center mx-auto select-none">
<div className="w-full sm:w-[500px] relative">{children}</div>
<div className="bg-black text-white min-h-screen select-none">
<div className="relative">{children}</div>
</div>
);
}
+10 -4
View File
@@ -8,10 +8,16 @@ export default function Overlay({
onClose: () => void;
}) {
return (
<div
onClick={onClose}
className="absolute bg-black/50 w-full h-full z-1 overflow-hidden flex justify-center items-center"
>
// <div onClick={onClose} className="fixed bg-black/50">
// <p
// onClick={onClose}
// className="absolute text-2xl font-bold top-4 right-4 bg-white text-black rounded-full p-2"
// >
// X
// </p>
// {children}
// </div>
<div onClick={onClose} className="fixed bg-black/50 w-full h-full z-1">
{children}
</div>
);
@@ -1,6 +1,6 @@
import { useState, useEffect } from "react";
import ScrollingText from "./ScrollingText";
import type { LastFMMusicObject } from "../utils/types";
import ScrollingText from "../ScrollingText";
import type { LastFMMusicObject } from "../../utils/types";
export default function MusicComponent() {
const [music, setMusic] = useState<LastFMMusicObject | null>(null);
@@ -1,6 +1,6 @@
import { useEffect, useRef } from "react";
export default function Countdown() {
export default function CountdownModule() {
const countdownRef = useRef<HTMLParagraphElement | null>(null);
const audioRef = useRef<HTMLAudioElement | null>(null);
+60
View File
@@ -0,0 +1,60 @@
import MusicComponent from "../info/MusicComponent";
import TVComponent from "../info/TVComponent";
export default function InfoModule() {
return (
<div className="border border-white border-solid rounded-lg p-2">
<div className="flex flex-wrap justify-between p-2 space-y-2">
<div>
<h1 className="text-2xl font-bold italic opacity-95">alex, 18</h1>
<img
src="https://storage.alexav.gg/content/6d87f5ac-e7f0-413c-84a6-6838e590b7d9.png"
className="rounded-md w-[150px] h-[110px] object-cover object-left-top"
alt="Profile"
/>
<div className="pt-2">
<MusicComponent />
<a
href="https://last.fm/user/lulawex"
target="_blank"
className="hover:underline w-fit opacity-50"
>
powered by last.fm
</a>
</div>
</div>
<div>
<h1 className="font-bold text-2xl italic">what i do</h1>
<p>
qa @{" "}
<a
href="https://medal.tv"
target="_blank"
rel="noopener noreferrer"
className="hover:underline text-[#bff83e]"
>
medal.tv
</a>
, game, code
</p>
<h1
className="italic opacity-50 font-semibold underline"
onClick={() => navigator.clipboard.writeText("alex@vierfrantz.com")}
>
alex@vierfrantz.com
</h1>
<hr className="my-2" />
<h1 className="font-bold text-2xl italic">obsessed with</h1>
<p>dexter, tlou, twd</p>
<hr className="my-2" />
<h1 className="font-bold text-2xl italic">status</h1>
<TVComponent />
</div>
</div>
</div>
);
}
+63
View File
@@ -0,0 +1,63 @@
import { useEffect, useState } from "react";
import { BillsScore, SabresScore } from "../../utils/types";
const IMAGES = {
bills: "https://storage.alexav.gg/content/bills.png",
sabres: "https://storage.alexav.gg/content/sabres.png",
};
export default function ScoreModule({ type }: { type: "sabres" | "bills" }) {
const [billsScore, setBillsScore] = useState<BillsScore | null>(null);
const [sabresScore, setSabresScore] = useState<SabresScore | null>(null);
useEffect(() => {
async function fetchBillsScore() {
const res = await fetch("https://api.alexav.gg/v4/scores/bills");
if (res.ok) {
const data = await res.json();
setBillsScore(data);
} else {
console.error("Failed to fetch Bills score; " + res.statusText);
}
}
async function fetchSabresScore() {
const res = await fetch("https://api.alexav.gg/v4/scores/sabres");
if (res.ok) {
const data = await res.json();
setSabresScore(data);
} else {
console.error("Failed to fetch Sabresscore; " + res.statusText);
}
}
if (type == "bills" && !billsScore) {
fetchBillsScore();
} else if (type === "sabres" && !sabresScore) {
fetchSabresScore();
}
}, []);
return (
<div className="border border-white border-solid rounded-lg w-full sm:w-[500px] mb-4">
<div className="flex justify-between">
<div>
<img width="100" className="p-4" src={IMAGES[type]} />
</div>
<div className="flex justify-center items-center px-6">
<div>
<h1 className="text-2xl">
{type === "bills"
? billsScore?.name
: `${sabresScore?.awayTeam.abbrev} @ ${sabresScore?.homeTeam.abbrev}`}
</h1>
<p className="float-right text-[20px]">
{type === "bills"
? billsScore?.score
: `${sabresScore && sabresScore?.sabresScore > sabresScore?.oppScore ? "W" : "L"} ${sabresScore?.sabresScore}-${sabresScore?.oppScore}`}
</p>
</div>
</div>
</div>
</div>
);
}
+7
View File
@@ -0,0 +1,7 @@
export default function WelcomeModule() {
return (
<div className="border border-white border-solid p-2 rounded-lg flex justify-between w-full">
<h1 className="text-2xl font-bold">welcome to my site !</h1>
</div>
);
}
+19 -64
View File
@@ -1,11 +1,12 @@
import { useState } from "react";
import Layout from "../components/Layout";
import Overlay from "../components/Overlay";
import MusicComponent from "../components/MusicComponent";
import TVComponent from "../components/TVComponent";
import GameComponent from "../components/GameComponent";
import FantasyStatus from "../components/FantasyStatus";
import GameComponent from "../components/info/GameComponent";
import PictureCarousel from "../components/modules/PictureCarousel";
import InfoModule from "../components/modules/InfoModule";
import WelcomeModule from "../components/modules/WelcomeModule";
import FantasyStatus from "../components/FantasyStatus";
import ScoreModule from "../components/modules/ScoreModule";
export default function App() {
const [selectedImage, setSelectedImage] = useState<string>("");
@@ -14,6 +15,7 @@ export default function App() {
<Layout>
{selectedImage !== "" && (
<Overlay onClose={() => setSelectedImage("")}>
<div className="flex justify-center items-center w-full h-full">
<img
draggable={false}
className="select-none"
@@ -21,74 +23,27 @@ export default function App() {
height="400"
src={selectedImage}
/>
</div>
</Overlay>
)}
<div className="my-2 space-y-4">
<PictureCarousel onClick={(url) => setSelectedImage(url)} />
<div className="border border-white border-solid p-2 rounded-lg flex justify-between">
<h1 className="text-2xl font-bold">welcome to my site !</h1>
</div>
<GameComponent />
<div className="border border-white border-solid rounded-lg p-2">
<div className="flex flex-wrap justify-between p-2 space-y-2">
<div>
<h1 className="text-2xl font-bold italic opacity-95">alex, 18</h1>
<div className="my-2 flex flex-col items-center sm:justify-center">
<div className="space-y-4 sm:w-[500px]">
<img
src="https://storage.alexav.gg/content/yeehaw.jpg"
className="rounded-md w-[150px] h-[110px] object-cover object-left-top"
alt="Profile"
/>
<div className="pt-2">
<MusicComponent />
<a
href="https://last.fm/user/lulawex"
target="_blank"
className="hover:underline w-fit opacity-50"
>
powered by last.fm
</a>
</div>
</div>
<div>
<h1 className="font-bold text-2xl italic">what i do</h1>
<p>
qa @{" "}
<a
href="https://medal.tv"
target="_blank"
rel="noopener noreferrer"
className="hover:underline text-[#bff83e]"
>
medal.tv
</a>
, game, code
</p>
<h1
className="italic opacity-50 font-semibold underline"
onClick={() =>
navigator.clipboard.writeText("alex@vierfrantz.com")
className="rounded-lg"
src={
"https://storage.alexav.gg/content/55f3eca0-a5a9-4c71-9d92-ba5d669a7a0c.jpg"
}
>
alex@vierfrantz.com
</h1>
/>
<hr className="my-2" />
<h1 className="font-bold text-2xl italic">obsessed with</h1>
<p>dexter, tlou, twd</p>
<hr className="my-2" />
<h1 className="font-bold text-2xl italic">status</h1>
<TVComponent />
</div>
</div>
</div>
<WelcomeModule />
<InfoModule />
<PictureCarousel onClick={(url) => setSelectedImage(url)} />
<GameComponent />
<ScoreModule type={"bills"} />
<FantasyStatus />
</div>
</div>
</Layout>
);
}
+34
View File
@@ -46,6 +46,38 @@ interface SleeperUser {
};
}
// scores
type BillsScore = {
name: string;
date: string;
score: string;
};
type SabresScore = {
gameDate: string;
wonInRegulation: boolean;
sabresScore: number;
oppScore: number;
homeTeam: NHLTeam;
awayTeam: NHLTeam;
};
type NHLTeam = {
id: number;
name: {
default: string;
fr: string;
};
commonName: {
default: string;
};
placeNameWithPreposition: {
default: string;
fr: string;
};
abbrev: string;
score: number;
logo: string;
};
export type {
LastFMMusicObject,
LastFMImageObject,
@@ -54,4 +86,6 @@ export type {
SleeperUser,
NFLAPIData,
NFLPlayer,
BillsScore,
SabresScore,
};