refactor: add slug to mii like route
This commit is contained in:
parent
4fec5f65f5
commit
f00c998c30
2 changed files with 25 additions and 19 deletions
|
|
@ -4,21 +4,20 @@ import { z } from "zod";
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
const likeSchema = z.object({
|
const slugSchema = z.coerce
|
||||||
miiId: z.coerce.number().int({ message: "Mii ID must be an integer" }).positive({ message: "Mii ID must be valid" }),
|
.number({ message: "Mii ID must be a number" })
|
||||||
});
|
.int({ message: "Mii ID must be an integer" })
|
||||||
|
.positive({ message: "Mii ID must be valid" });
|
||||||
export async function PATCH(request: NextRequest) {
|
|
||||||
// todo: rate limit
|
|
||||||
|
|
||||||
|
export async function PATCH(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
|
||||||
const body = await request.json();
|
const { id: slugId } = await params;
|
||||||
const parsed = likeSchema.safeParse(body);
|
const parsed = slugSchema.safeParse(slugId);
|
||||||
|
|
||||||
if (!parsed.success) return NextResponse.json({ error: parsed.error.errors[0].message }, { status: 400 });
|
if (!parsed.success) return NextResponse.json({ error: parsed.error.errors[0].message }, { status: 400 });
|
||||||
const { miiId } = parsed.data;
|
const miiId = parsed.data;
|
||||||
|
|
||||||
const result = await prisma.$transaction(async (tx) => {
|
const result = await prisma.$transaction(async (tx) => {
|
||||||
const existingLike = await tx.like.findUnique({
|
const existingLike = await tx.like.findUnique({
|
||||||
|
|
@ -6,31 +6,38 @@ import { Icon } from "@iconify/react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
likes: number;
|
likes: number;
|
||||||
miiId: number | undefined;
|
miiId?: number | undefined;
|
||||||
isLiked: boolean;
|
isLiked: boolean;
|
||||||
isLoggedIn: boolean;
|
isLoggedIn?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
big?: boolean;
|
big?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, big }: Props) {
|
export default function LikeButton({ likes, isLiked, miiId, isLoggedIn, disabled, big }: Props) {
|
||||||
const [isLikedState, setIsLikedState] = useState(isLiked);
|
const [isLikedState, setIsLikedState] = useState(isLiked);
|
||||||
const [likesState, setLikesState] = useState(likes);
|
const [likesState, setLikesState] = useState(likes);
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
|
if (disabled) return;
|
||||||
if (!isLoggedIn) redirect("/login");
|
if (!isLoggedIn) redirect("/login");
|
||||||
|
|
||||||
setIsLikedState((prev) => !prev);
|
setIsLikedState(!isLikedState);
|
||||||
setLikesState((prev) => (isLiked ? prev - 1 : prev + 1));
|
setLikesState(isLikedState ? likesState - 1 : likesState + 1);
|
||||||
|
|
||||||
const response = await fetch("/api/mii/like", { method: "PATCH", body: JSON.stringify({ miiId }) });
|
const response = await fetch(`/api/mii/${miiId}/like`, { method: "PATCH" });
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
const { liked, count } = await response.json();
|
const { liked, count } = await response.json();
|
||||||
|
|
||||||
setIsLikedState(liked);
|
setIsLikedState(liked);
|
||||||
setLikesState(count);
|
setLikesState(count);
|
||||||
|
} else {
|
||||||
|
setIsLikedState(isLikedState);
|
||||||
|
setLikesState(likesState);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button onClick={onClick} className={`flex items-center gap-2 text-red-400 cursor-pointer ${big ? "text-3xl" : "text-xl"}`}>
|
<button onClick={onClick} className={`flex items-center gap-2 text-red-400 ${disabled ? "" : "cursor-pointer"} ${big ? "text-3xl" : "text-xl"}`}>
|
||||||
<Icon icon={isLikedState ? "icon-park-solid:like" : "icon-park-outline:like"} />
|
<Icon icon={isLikedState ? "icon-park-solid:like" : "icon-park-outline:like"} />
|
||||||
<span>{likesState}</span>
|
<span>{likesState}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue