This commit is contained in:
Alex Frantz
2024-04-18 02:32:20 -04:00
parent 4b23ee7444
commit 2a63fd119c
21 changed files with 358 additions and 592 deletions
+21 -22
View File
@@ -1,30 +1,29 @@
import Link from "next/link"
import type { MouseEventHandler } from "react"
type HeaderItemProps = {
content: string,
linkTo: string,
onClick?: MouseEventHandler<HTMLButtonElement>, // don't even wanna bother
newWindow?: boolean
}
export default function HeaderItem(props: HeaderItemProps) {
if (props.onClick) {
return (
<>
<button className="inline hover:text-gray-500 hover:underline pr-2 "
onClick={props.onClick}
>
{props.content}
</button>
</>
)
} else {
return (
<p className="inline pr-2 hover:text-gray-500 hover:underline">
<Link href={props.linkTo} target={props.newWindow ? "_blank" : "_self"}>
{props.content}
</Link>
</p>
)
}
export default function HeaderItem({
content,
linkTo,
newWindow
}: HeaderItemProps) {
return (
<Link
className="inline text-green-500 hover:underline font-bold text-3xl pr-2"
href={linkTo}
target={newWindow ? "_blank" : "_self"}
>
{content}
</Link>
// <>
// <button className="inline text-green-500 hover:underline font-bold text-3xl pr-2"
// onClick={props.onClick}
// >
// {props.content}
// </button>
// </>
)
}
-19
View File
@@ -1,19 +0,0 @@
type InputOptionProps = {
label: string,
inputName: string,
isTextArea?: boolean
}
export default function InputOption(props: InputOptionProps) {
return (
<div className="pt-2 pb-2">
<label className="font-bold">{props.label}</label><br />
{
props.isTextArea ?
<textarea className="bg-gray-800 rounded-sm text-white resize-none h-32 w-72" name={props.inputName} />
:
<input className="bg-gray-800 rounded-sm text-white" name={props.inputName} />
}
</div>
)
}
-49
View File
@@ -1,49 +0,0 @@
import Image from "next/image";
import Link from "next/link";
import { api } from "@/utils/api";
export default function MusicCard() {
const {data: musicData, fetchStatus} = api.misc.song.useQuery()
return (
<div className="bg-white text-black max-w-fit mx-auto p-4">
<h1 className="text-2xl font-bold inline">Listening To</h1>
{/* link to lastfm */}
<Link
href="https://last.fm/user/lulawex"
target="_blank"
className="opacity-75 underline font-bold text-sm ml-2 hover:text-zinc-600"
>
Powered by Last.fm
</Link>
{
fetchStatus !== "fetching" ?
<div className="space-y-2">
{
musicData?.track.map((v,k) => {
return <div key={k}>
<Image
src={v.image[0]?.["#text"] ?? "https://storage.thatalex.dev/content/pfp.jpg"}
width="50"
height="50"
alt={`${v.name} Cover Art`}
className="inline mr-2"
/>
<div className="inline-block align-middle">
<Link href={v.url} target="_blank">
<h1 className="font-bold w-52 truncate hover:underline">{v.name}</h1>
</Link>
<p className="opacity-75">{v.artist["#text"]}</p>
</div>
</div>
})
}
</div>
:
<p className="font-bold">Hold tight, fetching..</p>
}
</div>
)
}
-8
View File
@@ -1,8 +0,0 @@
export default function NotFound() {
return (
<div className="text-white text-center">
<h1 className="font-bold text-2xl">Well, this is awkward..</h1>
<p>There&apos;s nothing here right now :/</p>
</div>
)
}
-38
View File
@@ -1,38 +0,0 @@
import Link from "next/link"
type ProjectCardProps = {
name: string,
technologies: string[],
subHeading?: string,
description: string,
urlTo: string
}
export default function ProjectCard(props: ProjectCardProps) {
const technologies = props.technologies.map((v,k) => {
return <div key={k} className="inline">
<div className="max-w-fit p-1 inline">
{v}
</div>
</div>
})
return (
<div className="bg-zinc-700 max-w-lg">
<div className="p-2 space-y-2 space-x-2">
<h1 className="font-bold text-2xl inline pl-2">{props.name}</h1>
<div className="inline-block">
{technologies}
</div>
<hr className="max-w-xs" />
<p>{props.description}</p>
<div className="bg-zinc-900 max-w-fit p-2 rounded-lg">
<Link href={props.urlTo} target="_blank">
<p>Source</p>
</Link>
</div>
</div>
</div>
)
}
-25
View File
@@ -1,25 +0,0 @@
import Image from "next/image"
import Link from 'next/link';
type ReviewCardProps = {
title: string,
image: string,
url: string,
showText: boolean
}
export default function ReviewCard(props: ReviewCardProps) {
return (
<Link href={props.url}>
<div className="inline">
<Image alt={props.title + " cover"} width="160" height="160" src={props.image} className="p-2" />
{
props.showText ?
<p className="font-bold pt-2 text-center">{props.title}</p>
:
""
}
</div>
</Link>
)
}
+4 -34
View File
@@ -1,51 +1,21 @@
// component imports
import Header from "./header";
import Footer from "./footer";
import Head from "./Head"
// react imports
import React from 'react';
// next modules
import { useSession } from "next-auth/react";
import Router from 'next/router';
type LayoutProps = {
children: React.ReactNode
protectedPage?: boolean
}
export default function RootLayout({ children, protectedPage }: LayoutProps) {
const {status} = useSession()
if (protectedPage) {
if (status === "loading") {
return (
<main className="min-h-screen bg-black">
<div className="w-1/2 mx-auto">
<Head />
<p>Loading...</p>
</div>
</main>
)
} else if (status === "unauthenticated") {
Router.replace("/").catch(() => {
console.error("Failed to reroute user!")
})
return (
<></>
)
}
}
export default function RootLayout({ children }: LayoutProps) {
return (
<main className="min-h-screen bg-black">
<div className="lg:w-1/2 sm:w-full mx-auto">
<Head />
<Header />
<main className="bg-black h-screen flex flex-col justify-center items-center overflow-y-hidden">
<Head />
<div className="flicker">
{children}
</div>
<Footer />
</main>
)
}
+96 -20
View File
@@ -1,27 +1,103 @@
import Link from "next/link"
import { Trash } from "grommet-icons"
import Image from "next/image";
import Link from "next/link";
import React, {useEffect, useState} from 'react';
import { api } from "@/utils/api";
// types
import type {
MedalApiObject,
SteamApiObject,
MusicApiObject
} from '@/utils/types'
type SocialCardProps = {
name: string,
id: number,
url: string,
isAuthenticated: boolean,
deleteCallback: () => void
platform: "steam" | "music" | "medal"
}
export default function SocialMediaCard(props: SocialCardProps) {
function MedalSocialCard() {
const { data: medalData, medalFetchStatus } = api.social.getMedalData.useQuery();
return (
<div className="bg-white p-5 w-full text-left">
<Link href={props.url} target="_blank">
<h1 className="inline font-bold">{props.name}</h1>
</Link>
{ props.isAuthenticated && (
<>
<Trash onClick={props.deleteCallback} color="black" className="float-right inline hover:cursor-pointer" />
<p className="float-right opacity-50 font-bold inline mr-2">ID: {props.id}</p>
</>
)}
</div>
<>
{
medalData?.data.map((v: MedalApiObject,k: number) => {
return <div key={k}>
<Image
src={v.image[0]?.["#text"] ?? "https://storage.thatalex.dev/content/pfp.jpg"}
width="50"
height="50"
alt={`${v.name} Cover Art`}
className="inline mr-2"
/>
<div className="inline-block align-middle">
<Link href={v.url} target="_blank">
<h1 className="font-bold w-52 truncate hover:underline">{v.name}</h1>
</Link>
<p className="opacity-75">{v.artist["#text"]}</p>
</div>
</div>
})
}
</>
)
}
function SteamSocialCard() {
const { data: SteamData, steamFetchStatus } = api.social.getSteamData.useQuery();
}
function MusicSocialCard() {
const { data: MusicData, musicFetchStatus } = api.social.getMusicData.useQuery();
return
}
export default function SocialCard({ platform }: SocialCardProps) {
const [content, setContent] = useState<React.JSX.Element | null>(null)
const platformDisplayElements = () => {
if (platform === "music") {
return (
<div className="space-y-2">
{
socialData?.data.map((v,k) => {
return <div key={k}>
<Image
src={v.image[0]?.["#text"] ?? "https://storage.thatalex.dev/content/pfp.jpg"}
width="50"
height="50"
alt={`${v.name} Cover Art`}
className="inline mr-2"
/>
<div className="inline-block align-middle">
<Link href={v.url} target="_blank">
<h1 className="font-bold w-52 truncate hover:underline">{v.name}</h1>
</Link>
<p className="opacity-75">{v.artist["#text"]}</p>
</div>
</div>
})
}
</div>
)
}
}
// return (
// <div className="bg-white text-black max-w-fit mx-auto p-4">
// <h1 className="text-2xl font-bold inline">{displayPlatform}</h1>
// </div>
// // <div className="bg-white text-black max-w-fit mx-auto p-4">
// // <h1 className="text-2xl font-bold inline">Listening To</h1>
// // {/* link to lastfm */}
// // <Link
// // href="https://last.fm/user/lulawex"
// // target="_blank"
// // className="opacity-75 underline font-bold text-sm ml-2 hover:text-zinc-600"
// // >
// // Powered by Last.fm
// // </Link>
// // </div>
// )
}
+4 -1
View File
@@ -5,12 +5,15 @@ export default function Footer() {
return (
<>
<div className="relative sm:w-1/2 m-auto mt-5 rounded-t-sm bg-zinc-900 p-2 text-white">
<div className="relative rounded-t-sm p-2 text-white opacity-50">
<p className="text-center">
<Link href="mailto:alex@alexavfrantz.com" className="hover:text-gray-500 hover:underline hover:cursor-pointer">
alex@alexavfrantz.com
</Link>
</p>
<p className="text-center">
The &apos;PipBoy&apos; is owned by Bethesda, I&apos;m just doing this for fun!
</p>
<p className="text-center">
&copy; Alex Frantz, {date.getFullYear()}
</p>
+16 -22
View File
@@ -1,31 +1,25 @@
import {useSession, signIn, signOut} from 'next-auth/react';
import HeaderItem from "./HeaderItem";
export default function Header() {
const { status } = useSession()
type HeaderProps = {
isNotHomePage: boolean
}
export default function Header({
isNotHomePage = false
}: HeaderProps) {
return (
<>
<div className="text-white max-w-sm mx-auto pt-2 pb-4">
<div className="inline-block pb-2">
<HeaderItem content="home" linkTo="/" />
<HeaderItem content="links" linkTo="/links" />
<HeaderItem content="projects" linkTo="/projects" />
{ status === "authenticated" &&
<HeaderItem
content="create"
linkTo="/create"
/>
}
<HeaderItem content={status == "unauthenticated" ? "login" : "logout" } onClick={async () => {
if (status == "unauthenticated") {
await signIn()
} else {
await signOut()
}
}} linkTo="" />
</div>
<hr />
<div className="inline-block pb-2 space-x-6 text-center">
<HeaderItem content="HOME" linkTo={
isNotHomePage ? "/?noAnimation"
: "/"
} />
<HeaderItem content="LINKS" linkTo="/links" />
<HeaderItem content="PROJECTS" linkTo="/projects" />
<HeaderItem content="ABOUT" linkTo="/about" />
</div>
<hr className="border-green-500" />
</div>
</>
)