fix: merge comparisons [id] and [slug] routes to resolve ambiguous route error

This commit is contained in:
Christopher Mayor
2026-04-28 08:31:01 -07:00
parent 1c6e36cc6f
commit 776f121eae
3 changed files with 116 additions and 115 deletions

View File

@@ -99,7 +99,7 @@ export default function ProfilePage() {
const handleToggleVisibility = async (comparison: Comparison) => {
try {
const res = await fetch(`/api/comparisons/${comparison.id}`, {
const res = await fetch(`/api/comparisons/${comparison.slug}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ isPublic: !comparison.isPublic }),
@@ -116,7 +116,7 @@ export default function ProfilePage() {
const handleDelete = async (comparison: Comparison) => {
if (!window.confirm(`Delete "${comparison.title}"? This cannot be undone.`)) return
try {
const res = await fetch(`/api/comparisons/${comparison.id}`, {
const res = await fetch(`/api/comparisons/${comparison.slug}`, {
method: "DELETE",
})
if (res.ok) {

View File

@@ -1,111 +0,0 @@
import { db } from "@/lib/db";
import { comparisons, sessions, users } from "@/lib/db/schema";
import { eq, and, gt } from "drizzle-orm";
import { headers } from "next/headers";
async function getAuthedUserId(): Promise<string | null> {
const hdrs = await headers();
const cookieHeader = hdrs.get("cookie") ?? "";
const cookieMatch = cookieHeader
.split(";")
.map((c) => c.trim())
.find(
(c) =>
c.startsWith("__Secure-better-auth.session_token=") ||
c.startsWith("better-auth.session_token=")
);
const token = cookieMatch
?.split("=")
?.slice(1)
?.join("=")
?.trim()
.split(".")[0];
if (!token) return null;
const sessionRows = await db
.select()
.from(sessions)
.where(and(eq(sessions.token, token), gt(sessions.expiresAt, new Date())))
.limit(1);
if (!sessionRows.length) return null;
const userRows = await db
.select()
.from(users)
.where(eq(users.id, sessionRows[0].userId))
.limit(1);
if (!userRows.length) return null;
return userRows[0].id;
}
export async function DELETE(
_request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const userId = await getAuthedUserId();
if (!userId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { id } = await params;
const existing = await db
.select({ userId: comparisons.userId })
.from(comparisons)
.where(eq(comparisons.id, id))
.limit(1);
if (!existing.length) {
return Response.json({ error: "Not found" }, { status: 404 });
}
if (existing[0].userId !== userId) {
return Response.json({ error: "Forbidden" }, { status: 403 });
}
await db.delete(comparisons).where(eq(comparisons.id, id));
return Response.json({ success: true });
}
export async function PATCH(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const userId = await getAuthedUserId();
if (!userId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { id } = await params;
const existing = await db
.select({ userId: comparisons.userId, isPublic: comparisons.isPublic })
.from(comparisons)
.where(eq(comparisons.id, id))
.limit(1);
if (!existing.length) {
return Response.json({ error: "Not found" }, { status: 404 });
}
if (existing[0].userId !== userId) {
return Response.json({ error: "Forbidden" }, { status: 403 });
}
const body = await request.json();
const newIsPublic =
typeof body.isPublic === "boolean" ? body.isPublic : !existing[0].isPublic;
const [updated] = await db
.update(comparisons)
.set({ isPublic: newIsPublic, updatedAt: new Date() })
.where(eq(comparisons.id, id))
.returning();
return Response.json({
id: updated.id,
isPublic: updated.isPublic,
});
}

View File

@@ -1,8 +1,45 @@
import { db } from "@/lib/db";
import { comparisons } from "@/lib/db/schema";
import { eq, sql } from "drizzle-orm";
import { comparisons, sessions, users } from "@/lib/db/schema";
import { eq, sql, and, gt } from "drizzle-orm";
import { headers } from "next/headers";
import { getComparison } from "@/app/actions/comparison";
async function getAuthedUserId(): Promise<string | null> {
const hdrs = await headers();
const cookieHeader = hdrs.get("cookie") ?? "";
const cookieMatch = cookieHeader
.split(";")
.map((c) => c.trim())
.find(
(c) =>
c.startsWith("__Secure-better-auth.session_token=") ||
c.startsWith("better-auth.session_token=")
);
const token = cookieMatch
?.split("=")
?.slice(1)
?.join("=")
?.trim()
.split(".")[0];
if (!token) return null;
const sessionRows = await db
.select()
.from(sessions)
.where(and(eq(sessions.token, token), gt(sessions.expiresAt, new Date())))
.limit(1);
if (!sessionRows.length) return null;
const userRows = await db
.select()
.from(users)
.where(eq(users.id, sessionRows[0].userId))
.limit(1);
if (!userRows.length) return null;
return userRows[0].id;
}
export async function GET(
_request: Request,
{ params }: { params: Promise<{ slug: string }> }
@@ -22,3 +59,78 @@ export async function GET(
return Response.json(comparison);
}
export async function DELETE(
_request: Request,
{ params }: { params: Promise<{ slug: string }> }
) {
const userId = await getAuthedUserId();
if (!userId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { slug } = await params;
const existing = await db
.select({ id: comparisons.id, userId: comparisons.userId })
.from(comparisons)
.where(eq(comparisons.slug, slug))
.limit(1);
if (!existing.length) {
return Response.json({ error: "Not found" }, { status: 404 });
}
if (existing[0].userId !== userId) {
return Response.json({ error: "Forbidden" }, { status: 403 });
}
await db.delete(comparisons).where(eq(comparisons.id, existing[0].id));
return Response.json({ success: true });
}
export async function PATCH(
request: Request,
{ params }: { params: Promise<{ slug: string }> }
) {
const userId = await getAuthedUserId();
if (!userId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { slug } = await params;
const existing = await db
.select({
id: comparisons.id,
userId: comparisons.userId,
isPublic: comparisons.isPublic,
})
.from(comparisons)
.where(eq(comparisons.slug, slug))
.limit(1);
if (!existing.length) {
return Response.json({ error: "Not found" }, { status: 404 });
}
if (existing[0].userId !== userId) {
return Response.json({ error: "Forbidden" }, { status: 403 });
}
const body = await request.json();
const newIsPublic =
typeof body.isPublic === "boolean" ? body.isPublic : !existing[0].isPublic;
const [updated] = await db
.update(comparisons)
.set({ isPublic: newIsPublic, updatedAt: new Date() })
.where(eq(comparisons.id, existing[0].id))
.returning();
return Response.json({
id: updated.id,
isPublic: updated.isPublic,
});
}