add some new fun things
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
+28
-73
@@ -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,80 +15,34 @@ export default function App() {
|
||||
<Layout>
|
||||
{selectedImage !== "" && (
|
||||
<Overlay onClose={() => setSelectedImage("")}>
|
||||
<img
|
||||
draggable={false}
|
||||
className="select-none"
|
||||
width="400"
|
||||
height="400"
|
||||
src={selectedImage}
|
||||
/>
|
||||
<div className="flex justify-center items-center w-full h-full">
|
||||
<img
|
||||
draggable={false}
|
||||
className="select-none"
|
||||
width="400"
|
||||
height="400"
|
||||
src={selectedImage}
|
||||
/>
|
||||
</div>
|
||||
</Overlay>
|
||||
)}
|
||||
|
||||
<div className="my-2 space-y-4">
|
||||
<PictureCarousel onClick={(url) => setSelectedImage(url)} />
|
||||
<div className="my-2 flex flex-col items-center sm:justify-center">
|
||||
<div className="space-y-4 sm:w-[500px]">
|
||||
<img
|
||||
className="rounded-lg"
|
||||
src={
|
||||
"https://storage.alexav.gg/content/55f3eca0-a5a9-4c71-9d92-ba5d669a7a0c.jpg"
|
||||
}
|
||||
/>
|
||||
|
||||
<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>
|
||||
<WelcomeModule />
|
||||
<InfoModule />
|
||||
<PictureCarousel onClick={(url) => setSelectedImage(url)} />
|
||||
<GameComponent />
|
||||
<ScoreModule type={"bills"} />
|
||||
<FantasyStatus />
|
||||
</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>
|
||||
<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")
|
||||
}
|
||||
>
|
||||
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>
|
||||
<FantasyStatus />
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user