import { getAllRows, getRowsWhereIn, insertRow, updateRow, getRowsWhereEquals, deleteRowsWhereEquals, deleteRowById, } from '../crud' import type { FeedbackDimension, FeedbackCategory, FeedbackCriterionItem, FeedbackDimensionPrompt } from '../../../src/db/types' import { AI_CONFIG } from '../../../src/config/constants' export interface FeedbackStructure { dimensions: FeedbackDimension[] categories: FeedbackCategory[] items: FeedbackCriterionItem[] } const byOrder = (rows: T[]) => [...rows].sort((a, b) => a.order - b.order) /** Vollständige, nach `order` sortierte Feedback-Taxonomie. */ export function loadFeedbackStructure(): FeedbackStructure { return { dimensions: byOrder(getAllRows('feedbackDimensions')), categories: byOrder(getAllRows('feedbackCategories')), items: byOrder(getAllRows('feedbackCriterionItems')), } } export const listFeedbackCategoriesOrdered = (): FeedbackCategory[] => byOrder(getAllRows('feedbackCategories')) export const listFeedbackCategoriesAll = (): FeedbackCategory[] => getAllRows('feedbackCategories') export const listFeedbackCriterionItemsAll = (): FeedbackCriterionItem[] => getAllRows('feedbackCriterionItems') export const getFeedbackCriterionItemsByIds = (ids: number[]): FeedbackCriterionItem[] => getRowsWhereIn('feedbackCriterionItems', 'id', ids) /** Legt zusätzlich einen Default-KI-Prompt für die neue Dimension an, siehe CLAUDE.md „Mehrstufiges Prompt-System". */ export function addFeedbackDimension(d: Omit): number { const id = insertRow('feedbackDimensions', d) insertRow('feedbackDimensionPrompts', { dimensionId: id, promptTemplate: AI_CONFIG.defaultDimensionPromptTemplate }) return id } export const updateFeedbackDimension = (id: number, patch: Partial): number => updateRow('feedbackDimensions', id, patch) /** Cascade: Items der Kategorien → Kategorien → Prompt-Konfiguration → Dimension. */ export function deleteFeedbackDimension(id: number): void { const cats = getRowsWhereEquals('feedbackCategories', 'dimensionId', id) for (const cat of cats) { deleteRowsWhereEquals('feedbackCriterionItems', 'categoryId', cat.id!) } deleteRowsWhereEquals('feedbackCategories', 'dimensionId', id) deleteRowsWhereEquals('feedbackDimensionPrompts', 'dimensionId', id) deleteRowById('feedbackDimensions', id) } /** * Selbstheilend: Dimensionen, die vor Einführung des Prompt-Systems (2026-07-07) angelegt wurden, * haben noch keine `feedbackDimensionPrompts`-Zeile — wird hier per Backfill nachgezogen, statt eine * separate Migration zu brauchen. */ export function listFeedbackDimensionPrompts(): FeedbackDimensionPrompt[] { const dims = getAllRows('feedbackDimensions') const existingDimIds = new Set(getAllRows('feedbackDimensionPrompts').map(p => p.dimensionId)) for (const dim of dims) { if (!existingDimIds.has(dim.id!)) { insertRow('feedbackDimensionPrompts', { dimensionId: dim.id!, promptTemplate: AI_CONFIG.defaultDimensionPromptTemplate }) } } return getAllRows('feedbackDimensionPrompts') } /** Selbstheilend wie `listFeedbackDimensionPrompts` — legt die Zeile bei Bedarf lazy an. */ export function getFeedbackDimensionPrompt(dimensionId: number): FeedbackDimensionPrompt { const existing = getRowsWhereEquals('feedbackDimensionPrompts', 'dimensionId', dimensionId)[0] if (existing) return existing const id = insertRow('feedbackDimensionPrompts', { dimensionId, promptTemplate: AI_CONFIG.defaultDimensionPromptTemplate }) return { id, dimensionId, promptTemplate: AI_CONFIG.defaultDimensionPromptTemplate } } export const updateFeedbackDimensionPrompt = (id: number, patch: Partial): number => updateRow('feedbackDimensionPrompts', id, patch) export const addFeedbackCategory = (c: Omit): number => insertRow('feedbackCategories', c) export const updateFeedbackCategory = (id: number, patch: Partial): number => updateRow('feedbackCategories', id, patch) /** Cascade: Items der Kategorie → Kategorie. */ export function deleteFeedbackCategory(id: number): void { deleteRowsWhereEquals('feedbackCriterionItems', 'categoryId', id) deleteRowById('feedbackCategories', id) } export const addFeedbackCriterionItem = (i: Omit): number => insertRow('feedbackCriterionItems', i) export const updateFeedbackCriterionItem = (id: number, patch: Partial): number => updateRow('feedbackCriterionItems', id, patch) export const deleteFeedbackCriterionItem = (id: number): void => deleteRowById('feedbackCriterionItems', id)