import type { Id } from "./_generated/dataModel" export type TicketChecklistItem = { id: string text: string done: boolean required?: boolean templateId?: Id<"ticketChecklistTemplates"> templateItemId?: string createdAt?: number createdBy?: Id<"users"> doneAt?: number doneBy?: Id<"users"> } export type TicketChecklistTemplateLike = { _id: Id<"ticketChecklistTemplates"> items: Array<{ id: string; text: string; required?: boolean }> } export function normalizeChecklistText(input: string) { return input.replace(/\r\n/g, "\n").trim() } export function checklistBlocksResolution(checklist: TicketChecklistItem[] | null | undefined) { return (checklist ?? []).some((item) => (item.required ?? true) && item.done !== true) } export function applyChecklistTemplateToItems( existing: TicketChecklistItem[], template: TicketChecklistTemplateLike, options: { now: number actorId?: Id<"users"> generateId?: () => string } ) { const generateId = options.generateId ?? (() => crypto.randomUUID()) const now = options.now const next = Array.isArray(existing) ? [...existing] : [] const existingKeys = new Set() for (const item of next) { if (!item.templateId || !item.templateItemId) continue existingKeys.add(`${String(item.templateId)}:${item.templateItemId}`) } let added = 0 for (const tplItem of template.items ?? []) { const templateItemId = String(tplItem.id ?? "").trim() const text = normalizeChecklistText(String(tplItem.text ?? "")) if (!templateItemId || !text) continue const key = `${String(template._id)}:${templateItemId}` if (existingKeys.has(key)) continue existingKeys.add(key) next.push({ id: generateId(), text, done: false, required: typeof tplItem.required === "boolean" ? tplItem.required : true, templateId: template._id, templateItemId, createdAt: now, createdBy: options.actorId, }) added += 1 } return { checklist: next, added } }