redesign list, add a few more cards
This commit is contained in:
@@ -35,7 +35,7 @@ export default function Footer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="lg:w-1/2 bg-gray-500 md:w-full mx-auto rounded-t-lg text-center p-4 select-none">
|
<div className="lg:w-1/2 bg-zinc-500 md:w-full mx-auto rounded-t-lg text-center p-4 select-none">
|
||||||
<h1 className="font-bold">© {new Date().getFullYear()}, Alex Frantz. All Rights Reserved</h1>
|
<h1 className="font-bold">© {new Date().getFullYear()}, Alex Frantz. All Rights Reserved</h1>
|
||||||
<p>All logos & images on this page belong to their respective owners.</p>
|
<p>All logos & images on this page belong to their respective owners.</p>
|
||||||
<p className="opacity-50 italic" onClick={drawNewQuote}>{quote}</p>
|
<p className="opacity-50 italic" onClick={drawNewQuote}>{quote}</p>
|
||||||
|
|||||||
@@ -1,25 +1,31 @@
|
|||||||
export default function ProjectComponent({
|
export default function ProjectComponent({
|
||||||
url,
|
url,
|
||||||
header,
|
header,
|
||||||
subheader,
|
projectHeader,
|
||||||
image,
|
projectSubheader,
|
||||||
imageSize = "100"
|
projectImage,
|
||||||
|
projectImageSize = "100"
|
||||||
}: {
|
}: {
|
||||||
url: string,
|
url: string,
|
||||||
header: string,
|
header: string,
|
||||||
subheader: string,
|
projectHeader: string,
|
||||||
image: string,
|
projectSubheader: string,
|
||||||
imageSize?: string
|
projectImage: string,
|
||||||
|
projectImageSize?: string
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<a href={url} target="_blank" className="max-w-fit mx-auto">
|
<a href={url} target="_blank" className="mx-auto">
|
||||||
<div className="bg-white text-black max-w-fit mx-auto p-2">
|
<div className="bg-white rounded-lg text-black w-full mx-auto p-2">
|
||||||
|
<div className="p-2">
|
||||||
|
<h1 className="text-center font-semibold">{header}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<img src={image} width={imageSize} />
|
<img src={projectImage} width={projectImageSize} />
|
||||||
|
|
||||||
<div className="flex flex-wrap mx-2">
|
<div className="flex flex-wrap mx-2">
|
||||||
<h1 className="font-bold w-full">{header}</h1>
|
<h1 className="font-bold w-[190px] text-left truncate whitespace-nowrap overflow-hidden">{projectHeader}</h1>
|
||||||
<h1>{subheader}</h1>
|
<h1 className="w-3/4 text-left truncate whitespace-nowrap overflow-hidden">{projectSubheader}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import ProjectComponent from '../ProjectComponent';
|
||||||
|
|
||||||
|
type MedalAPIResponse = {
|
||||||
|
data: MedalClip[]
|
||||||
|
}
|
||||||
|
type MedalClip = {
|
||||||
|
contentId: string,
|
||||||
|
contentTitle: string,
|
||||||
|
contentViews: number,
|
||||||
|
contentLikes: number,
|
||||||
|
contentThumbnail: string,
|
||||||
|
directClipUrl: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RecentClip() {
|
||||||
|
const [ data, setData ] = useState<MedalClip[]>();
|
||||||
|
const [ errorState, setErrorState ] = useState<string>("");
|
||||||
|
const [ loading, setLoading ] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const translateToWebsiteUrl = (url: string) => {
|
||||||
|
return url.replace('/clip/', "/clips/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// i'm a neat man what can i say
|
||||||
|
const likeOrLikes = (likes: number) => {
|
||||||
|
return (likes > 1 && likes !== 0) ? "likes" : "like"
|
||||||
|
}
|
||||||
|
const viewOrViews = (views: number) => {
|
||||||
|
return (views > 1 && views !== 0) ? "views" : "view"
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("https://api.alexav.gg/v4/social/medal", {
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json() as MedalAPIResponse
|
||||||
|
setData(data.data);
|
||||||
|
} else {
|
||||||
|
setErrorState("Failed to load! :(")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e: Error) => {
|
||||||
|
setErrorState(e.message)
|
||||||
|
})
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!loading && data) {
|
||||||
|
return (
|
||||||
|
<ProjectComponent
|
||||||
|
url={translateToWebsiteUrl(data[0].directClipUrl)}
|
||||||
|
header={"Clips I've taken"}
|
||||||
|
projectHeader={data[0].contentTitle}
|
||||||
|
projectSubheader={`${data[0].contentLikes} ${likeOrLikes(data[0].contentLikes)} | ${data[0].contentViews} ${viewOrViews(data[0].contentViews)}`}
|
||||||
|
projectImage={data[0].contentThumbnail}
|
||||||
|
projectImageSize={"80"}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
<>
|
||||||
|
<h1 className="font-bold text-2xl">No data :(</h1>
|
||||||
|
<p>Check out <a className="underline" href="https://medal.tv/u/alexav" target="_blank">medal.tv/u/alexav</a> if this isn't working.</p>
|
||||||
|
<p className="text-sm italic">{errorState}</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import ProjectComponent from '../ProjectComponent';
|
||||||
|
|
||||||
|
type SteamAPIResponse = {
|
||||||
|
data: GameItem[]
|
||||||
|
}
|
||||||
|
type GameItem = {
|
||||||
|
appid: number,
|
||||||
|
name: string,
|
||||||
|
playtime_forever: number,
|
||||||
|
img_icon_url: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RecentGame() {
|
||||||
|
const [ data, setData ] = useState<GameItem[]>();
|
||||||
|
const [ errorState, setErrorState ] = useState<string>("");
|
||||||
|
const [ loading, setLoading ] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const translateToAppStorePage = (appId: number) => {
|
||||||
|
return "https://store.steampowered.com/app/" + appId
|
||||||
|
}
|
||||||
|
const buildMediaUrl = (appId: number, hash: string) => {
|
||||||
|
return "https://media.steampowered.com/steamcommunity/public/images/apps/" + appId + "/" + hash + ".jpg"
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("https://api.alexav.gg/v4/social/steam", {
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (res.ok) {
|
||||||
|
const data = await res.json() as SteamAPIResponse
|
||||||
|
setData(data.data);
|
||||||
|
} else {
|
||||||
|
setErrorState("Failed to load! :(")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e: Error) => {
|
||||||
|
setErrorState(e.message)
|
||||||
|
})
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!loading && data) {
|
||||||
|
return (
|
||||||
|
<ProjectComponent
|
||||||
|
url={translateToAppStorePage(data[0].appid)}
|
||||||
|
header={"Games I'm playing"}
|
||||||
|
projectHeader={data[0].name}
|
||||||
|
projectSubheader={`${data[0].playtime_forever / 60}h played`}
|
||||||
|
projectImage={buildMediaUrl(data[0].appid, data[0].img_icon_url)}
|
||||||
|
projectImageSize={"40"}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
<>
|
||||||
|
<h1 className="font-bold text-2xl">No data :(</h1>
|
||||||
|
<p>Check out <a className="underline" href="https://steamcommunity.com/id/luvxavierr" target="_blank">steamcommunity.com/id/luvxavierr</a> if this isn't working.</p>
|
||||||
|
<p className="text-sm italic">{errorState}</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,9 +55,11 @@ export default function RecentListens() {
|
|||||||
return (
|
return (
|
||||||
<ProjectComponent
|
<ProjectComponent
|
||||||
url={"https://last.fm/user/lulawex"}
|
url={"https://last.fm/user/lulawex"}
|
||||||
header={data[0].name}
|
header={"Music I'm listening to"}
|
||||||
subheader={data[0].artist["#text"]}
|
projectHeader={data[0].name}
|
||||||
image={data[0].image.filter((v) => v.size === "large")[0]["#text"]}
|
projectSubheader={data[0].artist["#text"]}
|
||||||
|
projectImage={data[0].image.filter((v) => v.size === "medium")[0]["#text"]}
|
||||||
|
projectImageSize={"50"}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -49,11 +49,12 @@ export default function RecentPhoto() {
|
|||||||
if (data && !loading) {
|
if (data && !loading) {
|
||||||
return (
|
return (
|
||||||
<ProjectComponent
|
<ProjectComponent
|
||||||
url={"photos.alexav.gg"}
|
url={"https://photos.alexav.gg?id=" + data.id}
|
||||||
header={data.name}
|
header={"Photos I've captured"}
|
||||||
subheader={parseDate(data.dateTaken as Date)}
|
projectHeader={data.name}
|
||||||
image={data.imageUrl}
|
projectSubheader={parseDate(data.dateTaken as Date)}
|
||||||
imageSize={"150"}
|
projectImage={data.imageUrl}
|
||||||
|
projectImageSize={"85"}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -52,11 +52,12 @@ export default function RecentWatch() {
|
|||||||
if (data && !loading) {
|
if (data && !loading) {
|
||||||
return (
|
return (
|
||||||
<ProjectComponent
|
<ProjectComponent
|
||||||
header={data.title}
|
header={"What I'm watching"}
|
||||||
subheader={ data.finished ? "Finished!" : "Started on " + parseDate(data.startedOn) }
|
projectHeader={data.title}
|
||||||
|
projectSubheader={ data.finished ? "Finished!" : "Started on " + parseDate(data.startedOn) }
|
||||||
url={"https://watch.alexav.gg/?id=" + data.id}
|
url={"https://watch.alexav.gg/?id=" + data.id}
|
||||||
image={data.imageKey}
|
projectImage={data.imageKey}
|
||||||
imageSize={"50"}
|
projectImageSize={"30"}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+19
-24
@@ -6,6 +6,8 @@ import ContactForm from "./components/ContactForm";
|
|||||||
import RecentWatch from "./components/ProjectComponents/RecentWatch";
|
import RecentWatch from "./components/ProjectComponents/RecentWatch";
|
||||||
import RecentPhoto from "./components/ProjectComponents/RecentPhoto";
|
import RecentPhoto from "./components/ProjectComponents/RecentPhoto";
|
||||||
import RecentListens from "./components/ProjectComponents/RecentListens";
|
import RecentListens from "./components/ProjectComponents/RecentListens";
|
||||||
|
import RecentClip from './components/ProjectComponents/RecentClip';
|
||||||
|
import RecentGame from "./components/ProjectComponents/RecentGame";
|
||||||
import Layout from "./components/Layout";
|
import Layout from "./components/Layout";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
@@ -45,36 +47,29 @@ export default function Home() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="watching" className="my-5 py-5 px-4 bg-gray-500">
|
<section id="data" className="my-5 py-5 px-4 bg-zinc-500">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="text-center lg:text-left mb-4">
|
||||||
<div className="w-full flex justify-center items-center">
|
<h1 className="text-2xl font-bold">Data</h1>
|
||||||
<h1 className="text-4xl font-bold text-center">What I'm watching</h1>
|
<p>Cool data from some of my accounts/projects</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<hr className="my-2" />
|
||||||
<RecentWatch />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section id="photos" className="my-5 py-5 px-4">
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
||||||
<div className="w-full flex justify-center items-center">
|
|
||||||
<h1 className="text-4xl font-bold text-center">Photos I've captured</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div className="grid grid-cols-1 md:grid-cols-2 auto-cols-fr gap-4">
|
||||||
|
<div className="w-full min-w-[200px]">
|
||||||
|
<RecentListens />
|
||||||
|
</div>
|
||||||
|
<div className="w-full min-w-[200px]">
|
||||||
<RecentPhoto />
|
<RecentPhoto />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-full min-w-[200px]">
|
||||||
|
<RecentWatch />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<div className="w-full min-w-[200px]">
|
||||||
<section id="listens" className="my-5 py-5 px-4 bg-gray-500">
|
<RecentClip />
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
</div>
|
||||||
<div className="w-full flex justify-center items-center">
|
<div className="w-full min-w-[200px]">
|
||||||
<h1 className="text-4xl font-bold text-center w-full">Music I'm listening to</h1>
|
<RecentGame />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<RecentListens />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Reference in New Issue
Block a user