Initial commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"use server";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { rawDb, uniqueSlug } from "@/lib/db/client";
|
||||
|
||||
const EXCLUSIVE_GROUPS: string[][] = [["favorite", "vip"]];
|
||||
|
||||
function getExclusivePeers(categoryId: number): number[] {
|
||||
const cat = rawDb.prepare(`SELECT slug FROM actress_categories WHERE id = ?`).get(categoryId) as { slug: string } | undefined;
|
||||
if (!cat) return [];
|
||||
const group = EXCLUSIVE_GROUPS.find((g) => g.includes(cat.slug));
|
||||
if (!group) return [];
|
||||
const peers = group.filter((s) => s !== cat.slug);
|
||||
if (peers.length === 0) return [];
|
||||
const placeholders = peers.map(() => "?").join(",");
|
||||
const rows = rawDb.prepare(`SELECT id FROM actress_categories WHERE slug IN (${placeholders})`).all(...peers) as Array<{ id: number }>;
|
||||
return rows.map((r) => r.id);
|
||||
}
|
||||
|
||||
export async function toggleActressCategory(actressId: number, categoryId: number) {
|
||||
const exists = rawDb.prepare(`
|
||||
SELECT 1 FROM actress_categories_map WHERE actress_id = ? AND category_id = ?
|
||||
`).get(actressId, categoryId);
|
||||
if (exists) {
|
||||
rawDb.prepare(`DELETE FROM actress_categories_map WHERE actress_id = ? AND category_id = ?`).run(actressId, categoryId);
|
||||
} else {
|
||||
// Adding: also remove any peer category in an exclusive group.
|
||||
const peers = getExclusivePeers(categoryId);
|
||||
const tx = rawDb.transaction(() => {
|
||||
if (peers.length > 0) {
|
||||
const placeholders = peers.map(() => "?").join(",");
|
||||
rawDb.prepare(`
|
||||
DELETE FROM actress_categories_map
|
||||
WHERE actress_id = ? AND category_id IN (${placeholders})
|
||||
`).run(actressId, ...peers);
|
||||
}
|
||||
rawDb.prepare(`INSERT INTO actress_categories_map (actress_id, category_id) VALUES (?, ?)`).run(actressId, categoryId);
|
||||
});
|
||||
tx();
|
||||
}
|
||||
const a = rawDb.prepare(`SELECT slug FROM actresses WHERE id = ?`).get(actressId) as { slug: string } | undefined;
|
||||
revalidatePath("/actress");
|
||||
if (a) revalidatePath(`/actress/${a.slug}`);
|
||||
return { added: !exists };
|
||||
}
|
||||
|
||||
export async function setActressCategories(actressId: number, categoryIds: number[]) {
|
||||
const tx = rawDb.transaction(() => {
|
||||
rawDb.prepare(`DELETE FROM actress_categories_map WHERE actress_id = ?`).run(actressId);
|
||||
const ins = rawDb.prepare(`INSERT INTO actress_categories_map (actress_id, category_id) VALUES (?, ?)`);
|
||||
for (const id of categoryIds) ins.run(actressId, id);
|
||||
});
|
||||
tx();
|
||||
const a = rawDb.prepare(`SELECT slug FROM actresses WHERE id = ?`).get(actressId) as { slug: string } | undefined;
|
||||
revalidatePath("/actress");
|
||||
if (a) revalidatePath(`/actress/${a.slug}`);
|
||||
}
|
||||
|
||||
export async function createActressCategory(input: { name: string; color?: string | null; icon?: string | null; priority?: number }) {
|
||||
const trimmed = input.name.trim();
|
||||
if (!trimmed) return null;
|
||||
const existing = rawDb.prepare(`SELECT id, slug FROM actress_categories WHERE name = ?`).get(trimmed) as { id: number; slug: string } | undefined;
|
||||
if (existing) return existing;
|
||||
const slug = uniqueSlug(rawDb, "actress_categories", trimmed);
|
||||
const row = rawDb.prepare(`
|
||||
INSERT INTO actress_categories (name, slug, color, icon, priority, builtin)
|
||||
VALUES (?, ?, ?, ?, ?, 0) RETURNING id
|
||||
`).get(trimmed, slug, input.color ?? null, input.icon ?? null, input.priority ?? 50) as { id: number };
|
||||
revalidatePath("/actress");
|
||||
return { id: row.id, slug };
|
||||
}
|
||||
|
||||
export async function bulkAddCategory(actressIds: number[], categoryId: number) {
|
||||
if (actressIds.length === 0) return;
|
||||
const peers = getExclusivePeers(categoryId);
|
||||
const ins = rawDb.prepare(`INSERT OR IGNORE INTO actress_categories_map (actress_id, category_id) VALUES (?, ?)`);
|
||||
const tx = rawDb.transaction(() => {
|
||||
if (peers.length > 0) {
|
||||
const peerPh = peers.map(() => "?").join(",");
|
||||
const idPh = actressIds.map(() => "?").join(",");
|
||||
rawDb.prepare(`
|
||||
DELETE FROM actress_categories_map
|
||||
WHERE actress_id IN (${idPh}) AND category_id IN (${peerPh})
|
||||
`).run(...actressIds, ...peers);
|
||||
}
|
||||
for (const id of actressIds) ins.run(id, categoryId);
|
||||
});
|
||||
tx();
|
||||
revalidatePath("/actress");
|
||||
}
|
||||
|
||||
export async function bulkRemoveCategory(actressIds: number[], categoryId: number) {
|
||||
if (actressIds.length === 0) return;
|
||||
const placeholders = actressIds.map(() => "?").join(",");
|
||||
rawDb.prepare(`
|
||||
DELETE FROM actress_categories_map
|
||||
WHERE category_id = ? AND actress_id IN (${placeholders})
|
||||
`).run(categoryId, ...actressIds);
|
||||
revalidatePath("/actress");
|
||||
}
|
||||
|
||||
export async function deleteActressCategory(categoryId: number) {
|
||||
const row = rawDb.prepare(`SELECT builtin FROM actress_categories WHERE id = ?`).get(categoryId) as { builtin: number } | undefined;
|
||||
if (!row) return { ok: false, reason: "not found" };
|
||||
if (row.builtin) return { ok: false, reason: "built-in category cannot be deleted" };
|
||||
rawDb.prepare(`DELETE FROM actress_categories WHERE id = ?`).run(categoryId);
|
||||
revalidatePath("/actress");
|
||||
return { ok: true };
|
||||
}
|
||||
Reference in New Issue
Block a user