Updated links logic, new admin dash
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import Head from 'next/head';
|
||||
|
||||
export default function HeadTags() {
|
||||
return (
|
||||
<Head>
|
||||
<title>alexavfrantz</title>
|
||||
<meta property="og:title" content="alexavfrantz.com" />
|
||||
<meta property="og:description" content="Welcome to my personal website! See my favorite music, read my reviews on games and more!" />
|
||||
</Head>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// 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">
|
||||
<Head />
|
||||
<p>Loading...</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
if (status === "unauthenticated") {
|
||||
Router.replace("/").catch(() => {
|
||||
console.error("Failed to reroute user!")
|
||||
})
|
||||
} else {
|
||||
return (
|
||||
<main className="min-h-screen bg-black">
|
||||
<Head />
|
||||
<Header />
|
||||
{children}
|
||||
<Footer />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<main className="min-h-screen bg-black">
|
||||
<Head />
|
||||
<Header />
|
||||
{children}
|
||||
<Footer />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
import Link from "next/link"
|
||||
import { Trash } from "grommet-icons"
|
||||
|
||||
type SocialCardProps = {
|
||||
name: string,
|
||||
url: string
|
||||
url: string,
|
||||
showDelete: boolean,
|
||||
deleteCallback: () => void
|
||||
}
|
||||
|
||||
export default function SocialMediaCard(props: SocialCardProps) {
|
||||
@@ -11,6 +14,9 @@ export default function SocialMediaCard(props: SocialCardProps) {
|
||||
<Link href={props.url}>
|
||||
{props.name}
|
||||
</Link>
|
||||
{
|
||||
props.showDelete && <Trash onClick={props.deleteCallback} color="plain" className="pl-2 hover:cursor-pointer" />
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Twitter, LinkedinOption, MailOption } from "grommet-icons"
|
||||
import { Twitter, LinkedinOption } from "grommet-icons"
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Footer() {
|
||||
@@ -16,17 +16,13 @@ export default function Footer() {
|
||||
<p className="text-center">
|
||||
© Alex Frantz, 2023
|
||||
</p>
|
||||
<p className="text-center">
|
||||
<p className="text-center space-x-2">
|
||||
<Link href="https://twitter.com/avvex__" target="_blank" rel="noreferrer">
|
||||
<Twitter color='plain' className="pr-2" size="30" />
|
||||
<Twitter color='plain' size="30" />
|
||||
</Link>
|
||||
|
||||
<Link href="https://linkedin.com/in/thatalex" target="_blank" rel="noreferrer">
|
||||
<LinkedinOption className="pr-2" size="30" />
|
||||
</Link>
|
||||
|
||||
<Link href="mailto:alex@alexavfrantz.com" target="_blank" rel="noreferrer">
|
||||
<MailOption className="pr-2" size="30" />
|
||||
<LinkedinOption size="30" />
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -2,15 +2,22 @@ import {useSession, signIn, signOut} from 'next-auth/react';
|
||||
import HeaderItem from "./HeaderItem";
|
||||
|
||||
export default function Header() {
|
||||
const { data: session, status } = useSession()
|
||||
const { status } = useSession()
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="text-white w-52 pt-2 pb-4 mx-auto">
|
||||
<div className="text-white max-w-sm pt-2 pb-4 mx-auto">
|
||||
<p className="text-2xl font-bold">alex</p>
|
||||
<div className="inline-block pb-2">
|
||||
<HeaderItem content="home" linkTo="/" />
|
||||
<HeaderItem content="reviews" linkTo="/reviews" />
|
||||
<HeaderItem content="links" linkTo="/links" />
|
||||
{ status === "authenticated" &&
|
||||
<HeaderItem
|
||||
content="create"
|
||||
linkTo="/create"
|
||||
/>
|
||||
}
|
||||
<HeaderItem content={status == "unauthenticated" ? "login" : "logout" } onClick={async () => {
|
||||
if (status == "unauthenticated") {
|
||||
await signIn()
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// react modules
|
||||
import {useState} from 'react'
|
||||
import type {FormEvent} from 'react';
|
||||
|
||||
// trpc api
|
||||
import { api } from "@/utils/api";
|
||||
|
||||
// components
|
||||
import RootLayout from '@/components/RootLayout';
|
||||
import InputOption from '@/components/InputOption';
|
||||
|
||||
export default function CreatePage() {
|
||||
// ui states
|
||||
const [message, setMessage] = useState<string | null>(null)
|
||||
|
||||
// trpc hooks
|
||||
const postMutation = api.post.create.useMutation()
|
||||
const linksMutation = api.links.create.useMutation()
|
||||
|
||||
function sanitizeTitleForLink(title: string) {
|
||||
return title.replaceAll(" ", "-").toLowerCase()
|
||||
}
|
||||
|
||||
function onPostSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
const form = event.target as HTMLFormElement
|
||||
|
||||
const titleElement = form.elements.namedItem('title') as HTMLInputElement;
|
||||
const reviewElement = form.elements.namedItem('review') as HTMLInputElement;
|
||||
const imageElement = form.elements.namedItem('image') as HTMLInputElement;
|
||||
const typeElement = form.elements.namedItem('type') as HTMLInputElement;
|
||||
|
||||
if (!titleElement.value || !reviewElement.value || !imageElement.value || !typeElement.value) {
|
||||
event.preventDefault();
|
||||
|
||||
setMessage("One or more values were missing!")
|
||||
setTimeout(() => setMessage(null), 5000)
|
||||
} else {
|
||||
const object = {
|
||||
name: sanitizeTitleForLink(titleElement.value),
|
||||
reviewContents: reviewElement.value,
|
||||
image: imageElement.value,
|
||||
type: typeElement.value
|
||||
}
|
||||
|
||||
postMutation.mutate(object)
|
||||
}
|
||||
}
|
||||
|
||||
function onLinkSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
const form = event.target as HTMLFormElement
|
||||
const urlRegex = new RegExp("^((https):\/\/)?(www.)?[a-z0-9]+\.[a-z]+(\/[a-zA-Z0-9#]+\/?)*$")
|
||||
|
||||
const titleElement = form.elements.namedItem('title') as HTMLInputElement;
|
||||
const urlElement = form.elements.namedItem('url') as HTMLInputElement;
|
||||
const urlMatches = urlElement.value.match(urlRegex)
|
||||
|
||||
if (!titleElement.value || !urlElement.value) {
|
||||
event.preventDefault();
|
||||
|
||||
setMessage("One or more values were missing!")
|
||||
setTimeout(() => setMessage(null), 5000)
|
||||
} else if (urlMatches != null && !urlMatches[1]) {
|
||||
event.preventDefault();
|
||||
|
||||
setMessage("An invalid URL was provided!")
|
||||
setTimeout(() => setMessage(null), 5000)
|
||||
} else {
|
||||
const object = {
|
||||
name: titleElement.value,
|
||||
url: urlElement.value
|
||||
}
|
||||
|
||||
linksMutation.mutate(object)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<RootLayout protectedPage={true}>
|
||||
<div className="space-y-4">
|
||||
<div className="w-96 p-2 mx-auto bg-gray-500 text-center">
|
||||
<h1 className="font-bold text-2xl">Create Review Post</h1>
|
||||
|
||||
<div className="pt-2 pb-2">
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<form onSubmit={onPostSubmit}>
|
||||
<InputOption inputName="title" label="Title" />
|
||||
<InputOption inputName="image" label="Image URL" />
|
||||
<InputOption inputName="type" label="Content Type (book, movie, tv, game)" />
|
||||
<InputOption inputName="review" label="Review" isTextArea={true} />
|
||||
|
||||
<button className="bg-gray-800 text-white rounded-lg p-2" type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<p>{message}</p>
|
||||
</div>
|
||||
|
||||
<div className="w-96 p-2 mx-auto bg-gray-500 text-center">
|
||||
<h1 className="font-bold text-2xl">Create Link</h1>
|
||||
|
||||
<div className="pt-2 pb-2">
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<form onSubmit={onLinkSubmit}>
|
||||
<InputOption inputName="title" label="Title" />
|
||||
<InputOption inputName="url" label="URL" />
|
||||
|
||||
<button className="bg-gray-800 text-white rounded-lg p-2" type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<p>{message}</p>
|
||||
</div>
|
||||
</div>
|
||||
</RootLayout>
|
||||
)
|
||||
}
|
||||
+3
-8
@@ -1,22 +1,17 @@
|
||||
import Header from "@/components/header";
|
||||
import Footer from "@/components/footer";
|
||||
import RootLayout from "@/components/RootLayout";
|
||||
import Dropdown from "@/components/Dropdown";
|
||||
import ProjectCard from "@/components/ProjectsCard";
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="min-h-screen bg-black">
|
||||
<RootLayout>
|
||||
<div className="w-1/2 mx-auto text-white">
|
||||
<Header />
|
||||
|
||||
<Dropdown content={Music()} name="Music" />
|
||||
<Dropdown content={Games()} name="Games" />
|
||||
<Dropdown content={Projects()} name="Projects" />
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</main>
|
||||
</RootLayout>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+27
-30
@@ -1,40 +1,37 @@
|
||||
import Header from "@/components/header";
|
||||
import Footer from "@/components/footer";
|
||||
import SocialCard from '@/components/SocialCard'
|
||||
import Dropdown from "@/components/Dropdown";
|
||||
import RootLayout from '@/components/RootLayout';
|
||||
import { api } from "@/utils/api";
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import React from 'react';
|
||||
|
||||
export default function Links() {
|
||||
const {data: linkData} = api.links.getAll.useQuery()
|
||||
const [formatted, setFormatted] = useState<React.JSX.Element[] | null>(null)
|
||||
const {status} = useSession();
|
||||
|
||||
useEffect(() => {
|
||||
if (linkData) {
|
||||
setFormatted(
|
||||
linkData.map((v) => {
|
||||
return <SocialCard url={v.url} name={v.name} key={v.name} />
|
||||
})
|
||||
)
|
||||
}
|
||||
}, [linkData])
|
||||
// trpc hooks
|
||||
const { data: linkData } = api.links.getAll.useQuery()
|
||||
const deleteMutation = api.links.delete.useMutation()
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black">
|
||||
<div className="w-1/2 mx-auto text-white">
|
||||
<Header />
|
||||
|
||||
{formatted}
|
||||
|
||||
{/* {
|
||||
formatted ?
|
||||
<Dropdown content={formatted} name="Social Dropdown" />
|
||||
:
|
||||
<h1>There's nothing here :(</h1>
|
||||
} */}
|
||||
|
||||
<Footer />
|
||||
<RootLayout>
|
||||
<div className="space-y-2">
|
||||
{
|
||||
linkData && linkData.length > 0 ? linkData.map((v) => {
|
||||
return <SocialCard
|
||||
url={v.url}
|
||||
name={v.name}
|
||||
key={v.name}
|
||||
showDelete={status === "authenticated"}
|
||||
deleteCallback={() => {
|
||||
deleteMutation.mutate(v.id)
|
||||
}}
|
||||
/>
|
||||
}) :
|
||||
<div className="text-center text-white">
|
||||
<h1>Uh oh!</h1>
|
||||
<p>There's nothing here :(</p>
|
||||
</div>
|
||||
</main>
|
||||
}
|
||||
</div>
|
||||
</RootLayout>
|
||||
)
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
import Header from "@/components/header"
|
||||
import Footer from "@/components/footer"
|
||||
import RootLayout from "@/components/RootLayout"
|
||||
import Image from "next/image"
|
||||
import ProjectCard from "@/components/ProjectsCard"
|
||||
|
||||
export default function Resume() {
|
||||
return (
|
||||
<main className="min-h-screen bg-black">
|
||||
<Header />
|
||||
|
||||
<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" />
|
||||
@@ -64,8 +61,6 @@ export default function Resume() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
</RootLayout>
|
||||
)
|
||||
}
|
||||
@@ -1,35 +1,56 @@
|
||||
import {useRouter} from 'next/router';
|
||||
import Header from '@/components/header';
|
||||
import Footer from "@/components/footer";
|
||||
import Image from 'next/image';
|
||||
import {api} from '@/utils/api'
|
||||
import RootLayout from '@/components/RootLayout';
|
||||
|
||||
// next modules
|
||||
import Router, {useRouter} from 'next/router';
|
||||
import Link from 'next/link';
|
||||
import {useSession} from 'next-auth/react';
|
||||
import Image from 'next/image';
|
||||
|
||||
// api
|
||||
import {api} from '@/utils/api'
|
||||
|
||||
// icons
|
||||
import { Trash } from 'grommet-icons';
|
||||
|
||||
export default function ReviewPage() {
|
||||
const router = useRouter()
|
||||
const name = router.query.name as string
|
||||
const { status } = useSession()
|
||||
|
||||
// trpc stuff
|
||||
const {data: bookData} = api.post.getOne.useQuery(name)
|
||||
const deletionMutation = api.post.delete.useMutation()
|
||||
|
||||
function deleteItem() {
|
||||
if (bookData) {
|
||||
deletionMutation.mutate(bookData.id)
|
||||
Router.replace("/").catch(() => {
|
||||
console.error("Failed to reroute user!")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (bookData) {
|
||||
return (
|
||||
<main className="min-h-screen bg-black text-white">
|
||||
<Header />
|
||||
<div className="mx-auto w-1/2 text-center flex justify-center text-white">
|
||||
<RootLayout>
|
||||
<div className="mx-auto w-1/2 text-center flex justify-center">
|
||||
<Image src={bookData.image} width="150" height="150" alt={`${bookData.name} ${bookData.type} cover`} />
|
||||
</div>
|
||||
|
||||
<div className="mx-auto w-1/2 text-center">
|
||||
<h1 className="text-2xl font-bold">{bookData.name}</h1>
|
||||
<div className="mx-auto w-1/2 text-center text-white">
|
||||
<h1 className="text-2xl font-bold">{bookData.name} { status == "authenticated" ? <Trash onClick={deleteItem} className="hover:cursor-pointer" /> : ""}</h1>
|
||||
|
||||
<div className="pt-2 pb-2">
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
{bookData.reviewContents}
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</RootLayout>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<main className="min-h-screen bg-black text-white flex flex-col justify-center items-centers">
|
||||
<Header />
|
||||
<RootLayout>
|
||||
<div className="text-center text-2xl font-bold">
|
||||
<p>Well, that's not good..</p>
|
||||
</div>
|
||||
@@ -40,8 +61,7 @@ export default function ReviewPage() {
|
||||
Head Home
|
||||
</Link>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</RootLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import {useSession} from 'next-auth/react';
|
||||
import {useState, useEffect} from 'react';
|
||||
import type {FormEvent} from 'react';
|
||||
import Header from '@/components/header';
|
||||
import Footer from "@/components/footer";
|
||||
import Router from 'next/router';
|
||||
import { api } from "@/utils/api";
|
||||
|
||||
export default function Page() {
|
||||
const { data: session, status } = useSession()
|
||||
const postMutation = api.post.create.useMutation()
|
||||
const linksMutation = api.links.create.useMutation()
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (status == "unauthenticated") {
|
||||
console.log('user is unauthenticated!')
|
||||
Router.replace('/').catch(() => {
|
||||
console.error("Failed to reroute user!")
|
||||
})
|
||||
} else {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [status])
|
||||
|
||||
function sanitizeTitleForLink(title: string) {
|
||||
return title.replaceAll(" ", "-").toLowerCase()
|
||||
}
|
||||
|
||||
function onPostSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
const form = event.target as HTMLFormElement
|
||||
|
||||
const titleElement = form.elements.namedItem('title') as HTMLInputElement;
|
||||
const reviewElement = form.elements.namedItem('review') as HTMLInputElement;
|
||||
const imageElement = form.elements.namedItem('image') as HTMLInputElement;
|
||||
const typeElement = form.elements.namedItem('type') as HTMLInputElement;
|
||||
|
||||
const object = {
|
||||
name: sanitizeTitleForLink(titleElement.value),
|
||||
reviewContents: reviewElement.value,
|
||||
image: imageElement.value,
|
||||
type: typeElement.value
|
||||
}
|
||||
|
||||
postMutation.mutate(object)
|
||||
}
|
||||
|
||||
function onLinkSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
const form = event.target as HTMLFormElement
|
||||
|
||||
const titleElement = form.elements.namedItem('title') as HTMLInputElement;
|
||||
const urlElement = form.elements.namedItem('url') as HTMLInputElement;
|
||||
|
||||
const object = {
|
||||
name: sanitizeTitleForLink(titleElement.value),
|
||||
url: urlElement.value
|
||||
}
|
||||
|
||||
linksMutation.mutate(object)
|
||||
}
|
||||
|
||||
if (!loading) {
|
||||
return (
|
||||
<main className="min-h-screen bg-black color-white">
|
||||
<div className="w-1/2 mx-auto text-white">
|
||||
<Header />
|
||||
<form onSubmit={onPostSubmit} className="text-black">
|
||||
<div className="bg-gray-500 text-center">
|
||||
<label className="font-bold">Title</label><br />
|
||||
<input name="title" type="text" /><br />
|
||||
|
||||
<label className="font-bold">Image URL</label><br />
|
||||
<input name="image" type="text" /><br />
|
||||
|
||||
<label className="font-bold">Content Type (book, movie, tv, game)</label><br />
|
||||
<input name="type" type="text" /><br />
|
||||
|
||||
<label className="font-bold">Review</label><br />
|
||||
<textarea name="review" /><br />
|
||||
|
||||
<button type="submit">submit</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form onSubmit={onLinkSubmit} className="text-black">
|
||||
<div className="bg-gray-500 text-center">
|
||||
<label className="font-bold">Title</label><br />
|
||||
<input name="title" type="text" /><br />
|
||||
|
||||
<label className="font-bold">URL</label><br />
|
||||
<input name="url" type="text" /><br />
|
||||
|
||||
<button type="submit">submit</button>
|
||||
</div>
|
||||
</form>
|
||||
<Footer />
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<main>
|
||||
<p>
|
||||
Loading..
|
||||
</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
import Header from "@/components/header"
|
||||
import Footer from "@/components/footer";
|
||||
import RootLayout from "@/components/RootLayout"
|
||||
import ReviewCard from "@/components/ReviewCard"
|
||||
import {useSession} from 'next-auth/react';
|
||||
import {useState, useEffect} from 'react';
|
||||
import Link from 'next/link';
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import { api } from "@/utils/api";
|
||||
|
||||
type GenericItemType = {
|
||||
@@ -12,7 +9,6 @@ type GenericItemType = {
|
||||
}
|
||||
|
||||
export default function Reviews() {
|
||||
const { data: sessionData, status } = useSession();
|
||||
const {data: itemData} = api.post.getAll.useQuery()
|
||||
const [list, setList] = useState<null | JSX.Element[]>(null)
|
||||
const [type, setType] = useState("Book")
|
||||
@@ -62,20 +58,8 @@ export default function Reviews() {
|
||||
}, [itemData, type])
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black color-white">
|
||||
<Header />
|
||||
<RootLayout>
|
||||
<div className="w-1/2 mx-auto text-white">
|
||||
{
|
||||
status == "authenticated" ?
|
||||
<p className="text-center font-bold">
|
||||
<Link href="/reviews/create">
|
||||
Create
|
||||
</Link>
|
||||
</p>
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
<p className="text-center font-bold text-2xl hover:cursor-pointer hover:underline pb-2" onClick={onCatClick}>
|
||||
{type}
|
||||
</p>
|
||||
@@ -90,7 +74,6 @@ export default function Reviews() {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</RootLayout>
|
||||
)
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export const linksRouter = createTRPCRouter({
|
||||
.input(
|
||||
z.string().min(1)
|
||||
)
|
||||
.query(async ({ctx, input}) => {
|
||||
.mutation(async ({ctx, input}) => {
|
||||
return ctx.db.socialLink.delete({
|
||||
where: {
|
||||
id: input
|
||||
|
||||
@@ -32,7 +32,7 @@ export const postRouter = createTRPCRouter({
|
||||
.input(
|
||||
z.string().min(1)
|
||||
)
|
||||
.query(async ({ctx, input}) => {
|
||||
.mutation(async ({ctx, input}) => {
|
||||
return ctx.db.post.delete({
|
||||
where: {
|
||||
id: input
|
||||
|
||||
Reference in New Issue
Block a user