116 lines
3.0 KiB
TypeScript
116 lines
3.0 KiB
TypeScript
"use server";
|
|
|
|
import { db } from "@/lib/db";
|
|
import { comparisons, comparisonItems } from "@/lib/db/schema";
|
|
import type { ComparisonData } from "@/lib/types";
|
|
import { eq, desc, and } from "drizzle-orm";
|
|
import { createId } from "@paralleldrive/cuid2";
|
|
|
|
export async function createComparison(formData: FormData) {
|
|
const query = formData.get("query") as string;
|
|
const itemsRaw = formData.get("items") as string;
|
|
|
|
if (!query || !itemsRaw) {
|
|
return { error: "Query and items are required" };
|
|
}
|
|
|
|
const items: string[] = JSON.parse(itemsRaw);
|
|
if (!Array.isArray(items) || items.length < 2) {
|
|
return { error: "At least 2 items are required" };
|
|
}
|
|
|
|
const id = createId();
|
|
const title =
|
|
(formData.get("title") as string) ||
|
|
`Comparing ${items.join(" vs ")}`;
|
|
const slug =
|
|
title
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, "-")
|
|
.replace(/^-|-$/g, "")
|
|
.slice(0, 200) + `-${id.slice(-6)}`;
|
|
|
|
await db.insert(comparisons).values({
|
|
id,
|
|
userId: "system",
|
|
title,
|
|
query,
|
|
slug,
|
|
status: "researching",
|
|
});
|
|
|
|
return { id, slug };
|
|
}
|
|
|
|
export async function getComparison(
|
|
slug: string
|
|
): Promise<ComparisonData | null> {
|
|
const result = await db
|
|
.select()
|
|
.from(comparisons)
|
|
.where(eq(comparisons.slug, slug))
|
|
.limit(1);
|
|
|
|
if (!result.length) return null;
|
|
|
|
const comparison = result[0];
|
|
const items = await db
|
|
.select()
|
|
.from(comparisonItems)
|
|
.where(eq(comparisonItems.comparisonId, comparison.id))
|
|
.orderBy(comparisonItems.order);
|
|
|
|
return {
|
|
id: comparison.id,
|
|
userId: comparison.userId || "",
|
|
title: comparison.title,
|
|
query: comparison.query || "",
|
|
slug: comparison.slug,
|
|
status: comparison.status as ComparisonData["status"],
|
|
summary: comparison.summary || "",
|
|
items: items.map((item) => ({
|
|
name: item.name,
|
|
description: item.description || "",
|
|
overallScore:
|
|
(item.scores as Record<string, unknown>)?.overallScore as number ?? 0,
|
|
dimensions:
|
|
(item.scores as Record<string, unknown>)?.dimensions as Record<
|
|
string,
|
|
{ score: number; summary: string; details: string; pros?: string[]; cons?: string[] }
|
|
> ?? {},
|
|
pros: item.pros || [],
|
|
cons: item.cons || [],
|
|
})),
|
|
dimensions:
|
|
(comparison.overallData as Record<string, unknown>)?.dimensions as string[] ??
|
|
[],
|
|
tags: comparison.tags || [],
|
|
isPublic: comparison.isPublic ?? false,
|
|
viewCount: comparison.viewCount ?? 0,
|
|
createdAt: comparison.createdAt.toISOString(),
|
|
updatedAt: comparison.updatedAt.toISOString(),
|
|
};
|
|
}
|
|
|
|
export async function getUserComparisons(userId: string) {
|
|
return db
|
|
.select()
|
|
.from(comparisons)
|
|
.where(eq(comparisons.userId, userId))
|
|
.orderBy(desc(comparisons.createdAt));
|
|
}
|
|
|
|
export async function getPublicComparisons(limit = 20) {
|
|
return db
|
|
.select()
|
|
.from(comparisons)
|
|
.where(
|
|
and(
|
|
eq(comparisons.isPublic, true),
|
|
eq(comparisons.status, "completed")
|
|
)
|
|
)
|
|
.orderBy(desc(comparisons.createdAt))
|
|
.limit(limit);
|
|
}
|