This commit is contained in:
alex 3
2023-12-23 22:21:53 -05:00
parent 30173a5bbd
commit fe9e689e4d
14 changed files with 1694 additions and 83 deletions
+66
View File
@@ -0,0 +1,66 @@
import RootLayout from '@/components/RootLayout';
// next modules
import Router, {useRouter} from 'next/router';
import Link from 'next/link';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import {useSession} from 'next-auth/react';
// api
import {api} from '@/utils/api'
// icons
import { Trash } from 'grommet-icons';
export default function BlogPage() {
const router = useRouter()
const id = router.query.id as string
const { status } = useSession()
// trpc stuff
const {data: blogData} = api.blog.getOne.useQuery(id)
const deletionMutation = api.blog.delete.useMutation()
function deleteItem() {
if (blogData) {
deletionMutation.mutate(id)
Router.replace("/").catch(() => {
console.error("Failed to reroute user!")
})
}
}
if (blogData) {
return (
<RootLayout>
<div className="mx-auto w-1/2 text-white">
<h1 className="text-2xl font-bold text-center">{blogData.name} { status == "authenticated" ? <Trash onClick={deleteItem} className="hover:cursor-pointer" /> : ""}</h1>
<div className="pt-2 pb-2">
<hr />
</div>
<Markdown remarkPlugins={[remarkGfm]} className="text-white w-1/2 mx-auto">
{blogData.contents}
</Markdown>
</div>
</RootLayout>
)
} else {
return (
<RootLayout>
<div className="text-center text-2xl font-bold text-white">
<p>Well, that&apos;s not good..</p>
</div>
<div className="text-center text-white">
<p>You&apos;ve reached a page that doesn&apos;t exist. Lets fix that.</p>
<Link href="/" className="hover:underline hover:cursor-pointer hover:text-gray-500">
Head Home
</Link>
</div>
</RootLayout>
)
}
}
+78
View File
@@ -0,0 +1,78 @@
// trpc api
import { api } from "@/utils/api";
import {useState, useRef} from 'react';
import Markdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
// components
import RootLayout from '@/components/RootLayout';
// types
import type { FormEvent } from "react";
export default function BlogCreatePage() {
const [textContent, setTextContent] = useState<string | null>(null)
const [showMarkdown, setShowMarkdown] = useState<boolean>(false)
// element refs
const titleRef = useRef<HTMLInputElement>(null)
const tagRef = useRef<HTMLInputElement>(null)
const imageRef = useRef<HTMLInputElement>(null)
// trpc mutation
const blogPostMutation = api.blog.create.useMutation()
function handleElementUpdate(e: FormEvent) {
const textarea = e.target as HTMLTextAreaElement
setTextContent(textarea.value)
}
function submitBlogPost() {
if (!textContent || textContent == "") {
console.error("No text provided")
return;
}
if (!titleRef || !tagRef || !titleRef.current?.value || !tagRef.current?.value || titleRef.current?.value == "" || tagRef.current?.value == "") {
console.error("No title/tagline provided")
return;
}
if (!imageRef?.current?.value || imageRef.current?.value == "") {
console.error("No image URL provided")
return
}
const data = {
name: titleRef.current?.value,
tagline: tagRef.current?.value,
image: imageRef.current?.value,
contents: textContent,
}
blogPostMutation.mutate(data)
}
return (
<RootLayout protectedPage={true}>
<div className="text-center pb-2">
<button className="text-white mx-auto" onClick={() => setShowMarkdown(!showMarkdown)}>Show {showMarkdown ? "Text" : "Markdown"}</button>
</div>
{
showMarkdown ? <Markdown remarkPlugins={[remarkGfm]} className="text-white w-1/2 mx-auto">
{textContent}
</Markdown>
: <textarea onInput={handleElementUpdate} className="resize-none block h-96 w-1/2 mx-auto bg-gray-900 rounded-sm text-white" defaultValue={textContent ?? ""} />
}
<div className="text-center pt-4 space-y-2">
<input type="text" ref={titleRef} placeholder="title" name="title" /><br />
<input type="text" ref={imageRef} placeholder="image url" name="image" /><br />
<input type="text" ref={tagRef} placeholder="tagline" name="tag" /><br />
<button onClick={submitBlogPost} className="text-white">Submit</button>
</div>
</RootLayout>
)
}
+59
View File
@@ -0,0 +1,59 @@
import RootLayout from "@/components/RootLayout"
import BlogCard from "@/components/BlogCard"
import NotFound from "@/components/NotFound";
import React, {useState, useEffect} from 'react';
import { api } from "@/utils/api";
type GenericItemType = {
name: string,
image: string,
tagline: string,
id: string
}
export default function Blog() {
const {data: itemData, isLoading: areItemsLoading} = api.blog.getAll.useQuery()
const [list, setList] = useState<null | JSX.Element[]>(null)
useEffect(() => {
if (itemData) {
setList(
itemData.map((v: GenericItemType, k) => {
return <BlogCard
name={v.name}
tagline={v.tagline}
id={v.id}
image={v.image}
key={k}
/>
})
)
}
}, [itemData])
if (list) {
return (
<RootLayout>
<div className="text-white w-1/2 mx-auto">
<div className="space-x-2 space-y-2">
{
list.length > 0 ? list : <NotFound />
}
</div>
</div>
</RootLayout>
)
} else if (areItemsLoading) {
<RootLayout>
<div className="text-white">
<p>Loading..</p>
</div>
</RootLayout>
} else {
return (
<RootLayout>
<NotFound />
</RootLayout>
)
}
}
-66
View File
@@ -1,66 +0,0 @@
import RootLayout from "@/components/RootLayout"
import Image from "next/image"
import ProjectCard from "@/components/ProjectsCard"
export default function Resume() {
return (
<RootLayout>
<div className="text-center mx-auto text-white">
<div className="flex flex-wrap justify-center pb-2">
<Image src="https://storage.thatalex.dev/content/pfp.png" width="130" height="130" alt="PFP" className="rounded-3xl" />
</div>
<h1 className="text-2xl font-bold">Alex Frantz</h1>
<p>alex@alexavfrantz.com</p>
<p>Manual QA Tester + Test Automation Engineer</p>
<div className="flex flex-wrap w-8/12 mx-auto">
<div className="flex-1 p-4">
<h1 className="pb-2">Experience</h1>
<hr className="w-1/12 mx-auto" />
<div className="flex flex-col justify-center mx-auto pt-2">
<ProjectCard
key="1"
name="Medal.tv -- QA Engineer"
subHeading="Mar. 2022 - Present"
description="Testing features before anyone else to weed out breaking bugs. Also heading our test automation efforts to make testing as smooth as possible."
urlTo="https://medal.tv"
/>
</div>
<h1 className="pb-2 pt-2">Education</h1>
<hr className="w-1/12 mx-auto" />
<div className="flex flex-col justify-center mx-auto pt-2">
<ProjectCard
key="1"
name="Acellus Academy"
description="High school accrediation, studying Computer Science"
urlTo="https://medal.tv"
/>
</div>
</div>
<div className="flex-1 p-4">
<p className="pb-2">Skills</p>
<hr className="w-1/12 mx-auto" />
<ul className="pt-2 pb-2 list-disc list-inside">
<li>
Test Automation
</li>
<li>
End-to-end Testing
</li>
<li>
Customer Support
</li>
</ul>
<hr className="w-1/12 mx-auto" />
<p className="pt-2">Contact</p>
<p>Email: alex@alexavfrantz.com</p>
<p>LinkedIn: in/thatalex</p>
</div>
</div>
</div>
</RootLayout>
)
}