From f1fa52e747a65d625b29b35aa671a84feec5cc76 Mon Sep 17 00:00:00 2001 From: Blake Mealey Date: Fri, 11 Feb 2022 20:19:42 -0600 Subject: [PATCH] rename /work to /projects, add /fun --- .gitignore | 3 ++ _pages/fun.mdx | 10 ++++ _pages/home.mdx | 2 +- _pages/{work.mdx => projects.mdx} | 4 +- components/Layout.tsx | 5 +- components/MdxRenderer.tsx | 2 + components/RocketLeague.tsx | 72 +++++++++++++++++++++++++++++ components/rocket-league.module.css | 21 +++++++++ next.config.js | 6 +++ pages/[slug].tsx | 2 +- pages/api/rocket-league.ts | 34 ++++++++++++++ public/images/rocket-league.svg | 1 + styles/globals.css | 7 +-- 13 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 _pages/fun.mdx rename _pages/{work.mdx => projects.mdx} (95%) create mode 100644 components/RocketLeague.tsx create mode 100644 components/rocket-league.module.css create mode 100644 pages/api/rocket-league.ts create mode 100644 public/images/rocket-league.svg diff --git a/.gitignore b/.gitignore index 88b6f0d..aa18549 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +# secrets +.env + # dependencies /node_modules /.pnp diff --git a/_pages/fun.mdx b/_pages/fun.mdx new file mode 100644 index 0000000..76dc319 --- /dev/null +++ b/_pages/fun.mdx @@ -0,0 +1,10 @@ +--- +title: Fun +--- + +## Why not? + +I play a lot of Rocket League... this widget updates regularly with my latest time played according +to Steam. + + diff --git a/_pages/home.mdx b/_pages/home.mdx index 71d85df..3333828 100644 --- a/_pages/home.mdx +++ b/_pages/home.mdx @@ -8,7 +8,7 @@ Hi! I'm Blake Mealey, and this is my little corner of the internet. What's on this site: -- [~/work](/work): A list of projects I've built in my free +- [~/projects](/projects): A list of projects I've built in my free time - [~/posts](/posts): A collection of my thoughts diff --git a/_pages/work.mdx b/_pages/projects.mdx similarity index 95% rename from _pages/work.mdx rename to _pages/projects.mdx index af2ce2c..f31a180 100644 --- a/_pages/work.mdx +++ b/_pages/projects.mdx @@ -1,8 +1,8 @@ --- -title: Work +title: Projects --- -## Work +## Projects A list of projects I've built in my free time. diff --git a/components/Layout.tsx b/components/Layout.tsx index 9d93a72..216a3ee 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -56,11 +56,14 @@ const Layout: NextPage = ({ children, slug, meta }) => { home
  • - work + projects
  • posts
  • +
  • + fun +
  • diff --git a/components/MdxRenderer.tsx b/components/MdxRenderer.tsx index a009dd9..b26c5bf 100644 --- a/components/MdxRenderer.tsx +++ b/components/MdxRenderer.tsx @@ -3,6 +3,7 @@ import Link from 'next/link'; import createHeadingComponent from './createHeadingComponent'; import Shortcut from './Shortcut'; import Image from 'next/image'; +import RocketLeague from './RocketLeague'; const shortcodes = { Shortcut, @@ -19,6 +20,7 @@ const shortcodes = { h4: createHeadingComponent('h4'), h5: createHeadingComponent('h5'), h6: createHeadingComponent('h6'), + RocketLeague, }; const MdxRenderer = function ({ source }: { source: any }) { diff --git a/components/RocketLeague.tsx b/components/RocketLeague.tsx new file mode 100644 index 0000000..2299b5d --- /dev/null +++ b/components/RocketLeague.tsx @@ -0,0 +1,72 @@ +import { FC, useEffect, useState } from 'react'; +import styles from './rocket-league.module.css'; + +interface ResponseData { + minutes: number; +} + +type State = + | { + status: 'loading'; + } + | { status: 'loaded'; data: ResponseData } + | { status: 'error'; error: any }; + +const numberFormatter = new Intl.NumberFormat('en-US', { + style: 'unit', + unit: 'hour', + unitDisplay: 'long', +}); + +interface ContentProps { + state: State; +} + +const Content = ({ state }: ContentProps) => { + if (state.status === 'loading') { + return
    ...
    ; + } + + if (state.status === 'error') { + console.error(state.error); + return
    Something went wrong :(
    ; + } + + if (state.status === 'loaded') { + return ( +
    +
    Time played
    +
    {numberFormatter.format(state.data.minutes / 60)}
    +
    + ); + } + + return null; +}; + +export default function RocketLeague() { + const [state, setState] = useState({ + status: 'loading', + }); + useEffect(() => { + fetch('/api/rocket-league') + .then((res) => { + res + .json() + .then((data) => setState({ status: 'loaded', data })) + .catch((error) => { + setState({ status: 'error', error }); + }); + }) + .catch((error) => { + setState({ status: 'error', error }); + }); + }, []); + + return ( +
    + + +
    + ); +} diff --git a/components/rocket-league.module.css b/components/rocket-league.module.css new file mode 100644 index 0000000..2337ddb --- /dev/null +++ b/components/rocket-league.module.css @@ -0,0 +1,21 @@ +.container { + font-size: 40px; + padding: var(--theme-spacing-2) var(--theme-spacing-2); + border: 2px solid var(--theme-primary); + border-radius: var(--theme-roundness); + width: fit-content; + display: flex; + align-items: center; + gap: 1em; +} + +.logo { + width: 5em; +} + +.label { + font-size: 0.5em; + font-weight: bold; + opacity: 0.75; + margin-bottom: -0.5em; +} diff --git a/next.config.js b/next.config.js index ba1e598..6817e42 100644 --- a/next.config.js +++ b/next.config.js @@ -8,6 +8,12 @@ module.exports = { destination: '/home', permanent: true, }, + { + source: '/work', + destination: '/projects', + // Not totally sure that we want this to be permanent - maybe we want to have something else at /work in the future? + permanent: false, + }, ]; }, }; diff --git a/pages/[slug].tsx b/pages/[slug].tsx index caf2f63..99d06b2 100644 --- a/pages/[slug].tsx +++ b/pages/[slug].tsx @@ -49,7 +49,7 @@ export const getStaticProps: GetStaticProps = async ({ params }) => { export const getStaticPaths: GetStaticPaths = async () => { return { - paths: ['/home', '/work'], + paths: ['/home', '/projects', '/fun'], fallback: false, }; }; diff --git a/pages/api/rocket-league.ts b/pages/api/rocket-league.ts new file mode 100644 index 0000000..c909b03 --- /dev/null +++ b/pages/api/rocket-league.ts @@ -0,0 +1,34 @@ +import { NextApiRequest, NextApiResponse } from 'next'; + +const ROCKET_LEAGUE_APP_ID = 252950; + +async function getStats() { + const key = process.env.STEAM_API_KEY; + + const request = encodeURIComponent( + JSON.stringify({ + steamid: process.env.STEAM_ACCOUNT_ID, + appids_filter: [ROCKET_LEAGUE_APP_ID], + }) + ); + + const response = await fetch( + `https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=${key}&format=json&input_json=${request}` + ); + + return await response.json(); +} + +export default async function handler( + _req: NextApiRequest, + res: NextApiResponse +) { + const data = await getStats(); + const game = data.response.games.find( + (game: any) => game.appid === ROCKET_LEAGUE_APP_ID + ); + + // Cache for an hour across all users + res.setHeader('Cache-Control', 'public, s-maxage=3600, must-revalidate'); + res.status(200).json({ minutes: game.playtime_forever, time: Date.now() }); +} diff --git a/public/images/rocket-league.svg b/public/images/rocket-league.svg new file mode 100644 index 0000000..f5a2e48 --- /dev/null +++ b/public/images/rocket-league.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/styles/globals.css b/styles/globals.css index 1998747..7415183 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -124,12 +124,13 @@ h1 { a { color: var(--theme-secondary); - &:hover { - opacity: var(--theme-hover-opacity); - } transition: opacity 0.2s ease-in-out; } +a:hover { + opacity: var(--theme-hover-opacity); +} + main h1, main h2, main h3,