feat(20-02): add clientTranscripts data layer
schema.ts: clientTranscripts table (id, lead_id/client_id nullable FKs, title, content NOT NULL, call_date, created_at) + leadsRelations/ clientsRelations updated + clientTranscriptsRelations + TS types. lead-service.ts: getTranscripts(leadId) — call_date DESC ordering. actions.ts: addTranscript + deleteTranscript with requireAdmin guard, Zod validation, and revalidatePath. TypeScript: no errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
|
||||
import { z } from "zod";
|
||||
import { db } from "@/db";
|
||||
import { leads, quotes, tags } from "@/db/schema";
|
||||
import { leads, quotes, tags, clientTranscripts } from "@/db/schema";
|
||||
import { nanoid } from "nanoid";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import {
|
||||
createLeadSchema,
|
||||
@@ -252,3 +253,58 @@ export async function renameLeadTag(oldValue: string, newValue: string) {
|
||||
|
||||
revalidatePath("/admin/leads");
|
||||
}
|
||||
|
||||
// ── Transcript actions (Phase 20 — KB-02) ────────────────────────────────────
|
||||
|
||||
const addTranscriptSchema = z.object({
|
||||
lead_id: z.string().min(1),
|
||||
title: z.string().optional(),
|
||||
content: z.string().min(1, "Il testo del transcript è obbligatorio"),
|
||||
call_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Data non valida (YYYY-MM-DD)"),
|
||||
});
|
||||
|
||||
export async function addTranscript(data: z.infer<typeof addTranscriptSchema>) {
|
||||
await requireAdmin();
|
||||
|
||||
const parsed = addTranscriptSchema.safeParse(data);
|
||||
if (!parsed.success) {
|
||||
return { success: false, error: parsed.error.issues[0].message };
|
||||
}
|
||||
|
||||
try {
|
||||
const [transcript] = await db
|
||||
.insert(clientTranscripts)
|
||||
.values({
|
||||
id: nanoid(),
|
||||
lead_id: parsed.data.lead_id,
|
||||
title: parsed.data.title || null,
|
||||
content: parsed.data.content,
|
||||
call_date: parsed.data.call_date,
|
||||
})
|
||||
.returning();
|
||||
|
||||
revalidatePath(`/admin/leads/${parsed.data.lead_id}`);
|
||||
return { success: true, transcript };
|
||||
} catch (error) {
|
||||
console.error("addTranscript error:", error);
|
||||
return { success: false, error: "Errore nel salvataggio del transcript" };
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteTranscript(transcriptId: string, leadId: string) {
|
||||
await requireAdmin();
|
||||
|
||||
if (!transcriptId) throw new Error("ID transcript richiesto");
|
||||
|
||||
try {
|
||||
await db
|
||||
.delete(clientTranscripts)
|
||||
.where(eq(clientTranscripts.id, transcriptId));
|
||||
|
||||
revalidatePath(`/admin/leads/${leadId}`);
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("deleteTranscript error:", error);
|
||||
return { success: false, error: "Errore nell'eliminazione del transcript" };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user