oh hey yet another redesign
This commit is contained in:
@@ -57,15 +57,14 @@ export default function ContactForm() {
|
||||
}, [success]);
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-lg text-black p-2">
|
||||
<h1 className="text-2xl font-bold">Contact Me</h1>
|
||||
<hr className="my-2 border-black" />
|
||||
<div className="rounded-lg p-2 w-full md:w-[50%] mx-auto">
|
||||
<h1 className="text-2xl font-bold text-center pb-8">Contact Me</h1>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="space-y-2 text-center">
|
||||
<InputBox
|
||||
isText={true}
|
||||
name="name"
|
||||
placeholder="Name.."
|
||||
placeholder="Your name.."
|
||||
onChange={(value: string) => {
|
||||
setInputState((prevState) => {
|
||||
return {
|
||||
@@ -78,7 +77,7 @@ export default function ContactForm() {
|
||||
<InputBox
|
||||
name="email"
|
||||
isText={true}
|
||||
placeholder="Email.."
|
||||
placeholder="your@supercool.email"
|
||||
onChange={(value: string) => {
|
||||
setInputState((prevState) => {
|
||||
return {
|
||||
@@ -104,7 +103,7 @@ export default function ContactForm() {
|
||||
<InputBox
|
||||
isText={false}
|
||||
name="message"
|
||||
placeholder="Message.."
|
||||
placeholder="Your message here.."
|
||||
onChange={(value: string) => {
|
||||
setInputState((prevState) => {
|
||||
return {
|
||||
@@ -116,16 +115,26 @@ export default function ContactForm() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="block">
|
||||
<div className="block text-center">
|
||||
<button
|
||||
type="button"
|
||||
className="bg-black w-full text-white font-bold rounded-lg p-2"
|
||||
className="bg-white w-full text-black font-bold rounded-lg max-w-fit p-2"
|
||||
onClick={onSubmit}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
<p className="text-red-400 font-bold text-center">{error}</p>
|
||||
<p className="font-bold text-center">{ success && "Success! Your message has been received"}</p>
|
||||
|
||||
{
|
||||
error && (
|
||||
<p className="text-red-400 font-bold text-center pt-2">{error}</p>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
success && (
|
||||
<p className="font-bold text-green-500 text-center pt-2">Success! Your message has been received</p>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { GitHub, Bluesky, Twitter, Medal, Link, LinkedIn } from './SocialIcons';
|
||||
|
||||
export default function Footer() {
|
||||
const quoteArray = [
|
||||
"It works on my machine",
|
||||
"Revert 'Revert 'Revert 'Revert Change'''",
|
||||
"releases on Friday. refuses to elaborate. leaves.",
|
||||
"this is so cooked",
|
||||
"TypeScript: errors not for the weak, but for the spirited",
|
||||
"Professional Production Tester",
|
||||
"I break hearts to save lives. err.. something like that",
|
||||
"The best error is the one that never shows up",
|
||||
"go bills",
|
||||
"josh allen is my goat"
|
||||
]
|
||||
|
||||
// states
|
||||
const [mailState, setMailState] = useState<boolean>(false);
|
||||
const [ quote, setQuote ] = useState<string>(quoteArray[Math.floor(Math.random() * quoteArray.length)]);
|
||||
const [ mailState, setMailState ] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (mailState) {
|
||||
@@ -28,18 +13,9 @@ export default function Footer() {
|
||||
}
|
||||
}, [mailState])
|
||||
|
||||
const drawNewQuote = () => {
|
||||
const newQuote = quoteArray[Math.floor(Math.random() * quoteArray.length)]
|
||||
|
||||
// redraw if this quote == current quote
|
||||
if (newQuote !== quote) {
|
||||
setQuote(newQuote);
|
||||
} else drawNewQuote();
|
||||
}
|
||||
|
||||
return (
|
||||
<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>
|
||||
<div className="lg:w-1/2 md:w-full mx-auto rounded-t-lg text-center p-4 select-none">
|
||||
<h1 className="font-bold text-sm">© {new Date().getFullYear()}, Alex Frantz. All Rights Reserved</h1>
|
||||
<p>All logos & images on this page belong to their respective owners.</p>
|
||||
<RouterLink to={"/privacy"}>
|
||||
<p className="underline">Privacy</p>
|
||||
@@ -59,29 +35,6 @@ export default function Footer() {
|
||||
}} className="hover:underline">alex@alexav.gg</button>
|
||||
)
|
||||
}
|
||||
|
||||
<p className="opacity-50 italic" onClick={drawNewQuote}>{quote}</p>
|
||||
<div className="block space-x-2">
|
||||
{/* socials */}
|
||||
<a href="https://twitter.com/carlgrimesdupe" target="_blank">
|
||||
<Twitter />
|
||||
</a>
|
||||
<a href="https://bsky.app/profile/alexav.gg" target="_blank">
|
||||
<Bluesky />
|
||||
</a>
|
||||
<a href="https://linkedin.com/in/thatalex" target="_blank">
|
||||
<LinkedIn />
|
||||
</a>
|
||||
<a href="https://medal.tv/users/215577" target="_blank">
|
||||
<Medal />
|
||||
</a>
|
||||
<a href="https://github.com/azpha/website" target="_blank">
|
||||
<GitHub />
|
||||
</a>
|
||||
<a href="https://links.alexav.gg" target="_blank">
|
||||
<Link />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,14 +1,41 @@
|
||||
import { Link } from "react-router-dom"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<div className="text-white mx-auto pt-4 w-full sm:w-1/2 text-center lg:text-left">
|
||||
<Link to={"/"}>
|
||||
<h1 className="text-2xl font-bold hover:underline">Alex Frantz</h1>
|
||||
</Link>
|
||||
<p>Professional button clicker & word typer</p>
|
||||
const quoteArray = [
|
||||
"It works on my machine",
|
||||
"Revert 'Revert 'Revert",
|
||||
"'fuck the tests'",
|
||||
"this is so cooked",
|
||||
"Professional Production Tester",
|
||||
"I break hearts to save lives.",
|
||||
"go bills",
|
||||
"josh allen is my goat"
|
||||
]
|
||||
const [ quote, setQuote ] = useState<string>(quoteArray[Math.floor(Math.random() * quoteArray.length)]);
|
||||
|
||||
<hr className="my-4" />
|
||||
const drawNewQuote = () => {
|
||||
const newQuote = quoteArray[Math.floor(Math.random() * quoteArray.length)]
|
||||
|
||||
// redraw if this quote == current quote
|
||||
if (newQuote !== quote) {
|
||||
setQuote(newQuote);
|
||||
} else drawNewQuote();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-zinc-900 p-4 flex justify-between">
|
||||
<div>
|
||||
<a href="/" className="hover:underline">
|
||||
<h1 className="text-2xl font-bold">Alex Frantz</h1>
|
||||
</a>
|
||||
<p className="opacity-50 italic select-none" onClick={drawNewQuote}>{quote}</p>
|
||||
</div>
|
||||
<div className="space-x-2 items-center justify-center flex select-none">
|
||||
<a className="hover:underline" href="#about">About</a>
|
||||
<a className="hover:underline" href="#projects">Projects</a>
|
||||
<a className="hover:underline" href="#data">Data</a>
|
||||
<a className="hover:underline" href="#contact">Contact</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
export default function InputBox({
|
||||
name,
|
||||
placeholder,
|
||||
placeholder = "",
|
||||
isText = true,
|
||||
onChange
|
||||
}: {
|
||||
name: string,
|
||||
isText?: boolean,
|
||||
placeholder: string,
|
||||
placeholder?: string,
|
||||
onChange: (value: string) => void
|
||||
}) {
|
||||
if (isText) {
|
||||
@@ -16,7 +16,7 @@ export default function InputBox({
|
||||
type="text"
|
||||
name={name}
|
||||
placeholder={placeholder}
|
||||
className="bg-black rounded-lg p-2 text-white w-full"
|
||||
className="rounded-lg p-2 w-1/2 text-black"
|
||||
onChange={({target}) => onChange(target.value)}
|
||||
/>
|
||||
</div>
|
||||
@@ -28,7 +28,7 @@ export default function InputBox({
|
||||
name={name}
|
||||
placeholder={placeholder}
|
||||
onChange={({ target }) => onChange(target.value)}
|
||||
className="bg-black rounded-lg p-2 text-white w-full h-32"
|
||||
className="rounded-lg p-2 w-1/2 h-32 text-black"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function Layout({
|
||||
children: JSX.Element | JSX.Element[]
|
||||
}) {
|
||||
return (
|
||||
<main className="bg-black text-white min-h-screen">
|
||||
<main className="bg-black select-none text-white min-h-screen">
|
||||
<Header />
|
||||
{children}
|
||||
<Footer />
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
export default function Project({
|
||||
name,
|
||||
image,
|
||||
description,
|
||||
urlTo
|
||||
urlTo,
|
||||
tags
|
||||
}: {
|
||||
name: string,
|
||||
image: string,
|
||||
description: string,
|
||||
urlTo?: string,
|
||||
tags: string[]
|
||||
}) {
|
||||
return (
|
||||
<a href={urlTo} target="_blank">
|
||||
<div className="bg-white text-black mx-auto rounded-lg overflow-hidden max-w-full">
|
||||
<img
|
||||
src={image}
|
||||
alt={name}
|
||||
className="w-full h-24 object-cover"
|
||||
/>
|
||||
|
||||
<div className="bg-white text-black mx-auto rounded-lg overflow-hidden">
|
||||
<div className="p-4 space-y-2">
|
||||
<h1 className="font-bold text-xl">{name}</h1>
|
||||
<p>{description}</p>
|
||||
|
||||
<div className="space-x-2">
|
||||
{
|
||||
tags.map((v, k) => (
|
||||
<div className="bg-zinc-600 inline max-w-fit p-1 text-sm font-bold rounded-full bg-opacity-20" key={k}>{v}</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -14,18 +14,18 @@ export default function ProjectComponent({
|
||||
projectImageSize?: string
|
||||
}) {
|
||||
return (
|
||||
<a href={url} target="_blank" className="mx-auto">
|
||||
<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>
|
||||
<a href={url} target="_blank">
|
||||
<div className="bg-white rounded-lg text-black p-2">
|
||||
<h1 className="text-center font-semibold">{header}</h1>
|
||||
|
||||
<div className="flex items-center w-full">
|
||||
<img src={projectImage} width={projectImageSize} className="flex-shrink-0" />
|
||||
<div className="block">
|
||||
<div className="flex items-center">
|
||||
<img src={projectImage} width={projectImageSize} className="flex-shrink-0" />
|
||||
|
||||
<div className="flex flex-col mx-2 min-w-0 flex-grow">
|
||||
<h1 className="font-bold text-left truncate">{projectHeader}</h1>
|
||||
<h1 className="text-left truncate">{projectSubheader}</h1>
|
||||
<div className="flex flex-col mx-2 min-w-0 flex-grow">
|
||||
<h1 className="font-bold text-left truncate">{projectHeader}</h1>
|
||||
<h1 className="text-left truncate">{projectSubheader}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+82
-92
@@ -1,6 +1,7 @@
|
||||
import ListBox from "../components/ListBox";
|
||||
import Project from "../components/ProjectCard";
|
||||
import ContactForm from "../components/ContactForm";
|
||||
import Layout from "../components/Layout";
|
||||
import { GitHub, Bluesky, Twitter, Medal, LinkedIn } from '../components/Icons';
|
||||
|
||||
// project components
|
||||
import RecentWatch from "../components/ProjectComponents/RecentWatch";
|
||||
@@ -9,110 +10,99 @@ import RecentListens from "../components/ProjectComponents/RecentListens";
|
||||
import RecentClip from '../components/ProjectComponents/RecentClip';
|
||||
import RecentGame from "../components/ProjectComponents/RecentGame";
|
||||
import RecentBook from "../components/ProjectComponents/RecentBook";
|
||||
import Layout from "../components/Layout";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Layout>
|
||||
<div className="mx-auto w-full lg:w-1/2">
|
||||
<section id="projects" className="mb-4">
|
||||
<div className="text-center lg:text-left mb-4">
|
||||
<h1 className="text-2xl font-bold">Projects</h1>
|
||||
<p>Cool stuff I'm working on</p>
|
||||
<section id="about">
|
||||
<div className="w-full mx-auto text-center p-10">
|
||||
<div className="my-1">
|
||||
<h1 className="text-3xl font-bold">Hi, I'm Alex</h1>
|
||||
<p>I'm a junior developer working as QA + sometimes writing questionable code at <a className="hover:underline text-yellow-400" href="https://medal.tv" target="_blank">Medal.tv</a></p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<Project
|
||||
name="medaltv-wrapper"
|
||||
description="A JavaScript wrapper for the Medal.tv developer API"
|
||||
urlTo="https://github.com/azpha/medaltv-wrapper"
|
||||
image="https://storage.alexav.gg/content/medal-logo.png"
|
||||
/>
|
||||
<Project
|
||||
name="splitstat"
|
||||
description="A Discord bot for SplitStat: Arena Warfare statistics"
|
||||
urlTo="https://github.com/azpha/splitstat"
|
||||
image="https://storage.alexav.gg/content/splitstat-logo.png"
|
||||
/>
|
||||
<Project
|
||||
name="steam-deck-file-sync"
|
||||
description="Sync clips from Steam Deck"
|
||||
urlTo="https://github.com/azpha/steam-deck-file-sync"
|
||||
image="https://storage.alexav.gg/content/steam-deck.jpg"
|
||||
/>
|
||||
<Project
|
||||
name="subscription-tracker"
|
||||
description="Easily track upcoming subscriptions"
|
||||
urlTo="https://github.com/azpha/subscription-tracker"
|
||||
image="https://storage.alexav.gg/content/a7a289ac-9466-4f3f-b904-2f9be897e0f7.png"
|
||||
/>
|
||||
<div className="block space-x-2">
|
||||
{/* socials */}
|
||||
<a href="https://twitter.com/carlgrimesdupe" target="_blank">
|
||||
<Twitter />
|
||||
</a>
|
||||
<a href="https://bsky.app/profile/alexav.gg" target="_blank">
|
||||
<Bluesky />
|
||||
</a>
|
||||
<a href="https://medal.tv/users/215577" target="_blank">
|
||||
<Medal />
|
||||
</a>
|
||||
<a href="https://github.com/azpha/website" target="_blank">
|
||||
<GitHub />
|
||||
</a>
|
||||
<a href="https://linkedin.com/in/thatalex" target="_blank">
|
||||
<LinkedIn />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<section id="data" className="my-5 py-5 px-4 bg-zinc-500">
|
||||
<div className="text-center lg:text-left mb-4">
|
||||
<h1 className="text-2xl font-bold">Data</h1>
|
||||
<p>Cool data from some of my accounts/projects</p>
|
||||
|
||||
<hr className="my-2" />
|
||||
<div className="my-4">
|
||||
<a className="p-2 bg-white text-black rounded-lg" href="#projects">View My Work</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<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 />
|
||||
</div>
|
||||
<div className="w-full min-w-[200px]">
|
||||
<RecentWatch />
|
||||
</div>
|
||||
<div className="w-full min-w-[200px]">
|
||||
<RecentBook />
|
||||
</div>
|
||||
<div className="w-full min-w-[200px]">
|
||||
<RecentClip />
|
||||
</div>
|
||||
<div className="w-full min-w-[200px]">
|
||||
<RecentGame />
|
||||
</div>
|
||||
<section id="projects">
|
||||
<div className="bg-zinc-900 py-8">
|
||||
<h1 className="pb-8 text-3xl text-center font-bold">My Projects</h1>
|
||||
|
||||
<div className="p-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 w-full md:w-[70%] lg:w-[50%] mx-auto">
|
||||
<Project
|
||||
name="medaltv-wrapper"
|
||||
description="A JavaScript wrapper for the Medal.tv developer API"
|
||||
urlTo="https://github.com/azpha/medaltv-wrapper"
|
||||
tags={["JavaScript"]}
|
||||
/>
|
||||
<Project
|
||||
name="splitstat"
|
||||
description="A Discord bot for SplitStat: Arena Warfare statistics"
|
||||
urlTo="https://github.com/azpha/splitstat"
|
||||
tags={["JavaScript", "DiscordJS"]}
|
||||
/>
|
||||
<Project
|
||||
name="steam-deck-file-sync"
|
||||
description="Sync clips from Steam Deck"
|
||||
urlTo="https://github.com/azpha/steam-deck-file-sync"
|
||||
tags={["Python", "Flask"]}
|
||||
/>
|
||||
<Project
|
||||
name="subscription-tracker"
|
||||
description="Track upcoming subscriptions"
|
||||
urlTo="https://github.com/azpha/subscription-tracker"
|
||||
tags={["JavaScript", "ReactJS", "Vite"]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="about" className="my-5 p-4">
|
||||
<div className="container max-w-5xl mx-auto">
|
||||
<div className="grid lg:grid-cols-2 md:grid-cols-1 gap-8">
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold">About Me</h2>
|
||||
<p className="text-muted-foreground mt-4">
|
||||
I'm a "junior" developer with a passion for software and games.
|
||||
I have experience in languages like JavaScript and Python, and am primarily
|
||||
working in libraries like React.
|
||||
</p>
|
||||
<div className="mt-8 grid grid-cols-2 w-full mx-auto gap-4">
|
||||
<ListBox
|
||||
title="Skills"
|
||||
points={[
|
||||
"JavaScript",
|
||||
"Python",
|
||||
"Java",
|
||||
"SQL",
|
||||
"Prisma"
|
||||
]}
|
||||
/>
|
||||
<ListBox
|
||||
title="Experience"
|
||||
points={[
|
||||
"Working at Medal.tv as a QA tester",
|
||||
"4 years as a JavaScript developer",
|
||||
"Worked on various side-projects"
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ContactForm />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="data">
|
||||
<div className="py-8">
|
||||
<h1 className="pb-8 text-3xl text-center font-bold">My Data</h1>
|
||||
|
||||
<div className="p-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 w-full md:w-[70%] lg:w-[50%] mx-auto">
|
||||
<RecentListens />
|
||||
<RecentPhoto />
|
||||
<RecentWatch />
|
||||
<RecentBook />
|
||||
<RecentClip />
|
||||
<RecentGame />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="contact">
|
||||
<div className="bg-zinc-900 py-8">
|
||||
<ContactForm />
|
||||
</div>
|
||||
</section>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user