From 96a8b655f0b12c67b5e45c8619dfca48d1f40d2d Mon Sep 17 00:00:00 2001 From: Alex Frantz Date: Mon, 7 Sep 2026 16:29:18 -0400 Subject: [PATCH] add blog post, projects --- src/components/BlogRow.tsx | 33 +++++++++++++++++++ src/components/ErrorState.tsx | 36 ++++----------------- src/components/info/GameComponent.tsx | 34 +++++++------------ src/components/info/MusicComponent.tsx | 45 +++++++++++--------------- src/components/modules/StatModule.tsx | 4 +-- src/pages/App.tsx | 20 +++++++++++- src/utils/types.ts | 8 +++++ 7 files changed, 99 insertions(+), 81 deletions(-) create mode 100644 src/components/BlogRow.tsx diff --git a/src/components/BlogRow.tsx b/src/components/BlogRow.tsx new file mode 100644 index 0000000..ec8aaa9 --- /dev/null +++ b/src/components/BlogRow.tsx @@ -0,0 +1,33 @@ +import ErrorState from "./ErrorState"; +import { useState, useEffect } from "react"; +import type { BlogPost } from "../utils/types"; + +export default function BlogRow() { + const [post, setPost] = useState(null); + + useEffect(() => { + fetch("https://blog.alexav.gg/api/posts", { + method: "GET", + }).then(async (res) => { + if (res.ok) { + try { + const data = await res.json(); + setPost(data[0]); + } catch (e) { + console.error("An error occurred fetching blog posts!", e); + } + } else console.error("Failed to fetch blog posts!"); + }); + }, []); + + if (post) { + return ( +
+ +

{post?.title}

+

{post?.description}

+
+
+ ); + } else return ; +} diff --git a/src/components/ErrorState.tsx b/src/components/ErrorState.tsx index 11f7c7b..7bcdfd7 100644 --- a/src/components/ErrorState.tsx +++ b/src/components/ErrorState.tsx @@ -1,31 +1,9 @@ -export default function ErrorState({ - type = "error", -}: { - type: "error" | "loading" | "unavailable"; -}) { - if (type === "error") { - return ( -
-
-

whoops, something went wrong

-
+export default function ErrorState({ label }: { label: string }) { + return ( +
+
+

{label}

- ); - } else if (type === "loading") { - return ( -
-
-

loading..

-
-
- ); - } else if (type === "unavailable") { - return ( -
-
-

no game launched recently

-
-
- ); - } +
+ ); } diff --git a/src/components/info/GameComponent.tsx b/src/components/info/GameComponent.tsx index 2b9b641..b68440a 100644 --- a/src/components/info/GameComponent.tsx +++ b/src/components/info/GameComponent.tsx @@ -34,29 +34,17 @@ export default function GameComponent() { fetchGame(); }, []); - if (game) { - return ( - -
-
- -
-

- {game.currentlyPlaying.game} -

-

- {" "} - since{" "} - {new Date( - game.currentlyPlaying.startedPlayingAt, - ).toLocaleTimeString()} -

-
+ return ( +
+ + + ); } diff --git a/src/components/info/MusicComponent.tsx b/src/components/info/MusicComponent.tsx index 5abe37a..69d3640 100644 --- a/src/components/info/MusicComponent.tsx +++ b/src/components/info/MusicComponent.tsx @@ -1,10 +1,8 @@ import { useState, useEffect } from "react"; import type { LastFMMusicObject } from "../../utils/types"; -import ErrorState from "../ErrorState"; export default function MusicComponent() { const [music, setMusic] = useState(null); - const [failedFetch, setFailedFetch] = useState(false); useEffect(() => { async function fetchMusic() { @@ -13,10 +11,9 @@ export default function MusicComponent() { if (response.ok) { const data = await response.json(); setMusic(data as LastFMMusicObject); - } else setFailedFetch(true); + } } catch (e) { console.error("Failed to fetch music!", e); - setFailedFetch(true); } } @@ -26,27 +23,23 @@ export default function MusicComponent() { fetchMusic(); }, []); - if (!failedFetch) { - if (music) { - return ( - -
-
-
-

- Currently Playing - - {music.title} by{" "} - {music.artist} -

-
-
+ return ( +
+ + + ); } diff --git a/src/components/modules/StatModule.tsx b/src/components/modules/StatModule.tsx index 58137fc..da739e9 100644 --- a/src/components/modules/StatModule.tsx +++ b/src/components/modules/StatModule.tsx @@ -67,9 +67,9 @@ export default function StatModule() { ); } else { - return ; + return ; } } else { - return ; + return ; } } diff --git a/src/pages/App.tsx b/src/pages/App.tsx index fd086cb..af675b3 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -3,6 +3,9 @@ import ProjectCard from "../components/ProjectCard"; import FantasyStatus from "../components/FantasyStatus"; import PictureCarousel from "../components/modules/PictureCarousel"; import Footer from "../components/Footer"; +import BlogRow from "../components/BlogRow"; +import GameComponent from "../components/info/GameComponent"; +import MusicComponent from "../components/info/MusicComponent"; export default function App() { return ( @@ -43,6 +46,15 @@ export default function App() {
+

+ + LATEST BLOG POST + +

+ + +
+

THINGS I'VE BUILT

-

FUN STUFF

+

MY ACTIVITIES

+ +
+ + +
+

Fantasy

diff --git a/src/utils/types.ts b/src/utils/types.ts index b2de279..1cc8aeb 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -93,6 +93,13 @@ type MLBTeam = { score: number; }; +interface BlogPost { + id: number; + title: string; + description: string; + slug: string; +} + export type { LastFMMusicObject, LastFMImageObject, @@ -104,4 +111,5 @@ export type { BillsScore, SabresScore, YankeesScore, + BlogPost, };