Sichert den lokalen Entwicklungsstand nach Gitea: Nav/Dashboard, Personen-Excel/Archiv, Team-Setup, Assignment-Übergabe und C6/C7/T2. Co-authored-by: Cursor <cursoragent@cursor.com>
71 lines
3.4 KiB
TypeScript
71 lines
3.4 KiB
TypeScript
import {
|
|
getAllRows, getRowsWhereEquals, getRowsWhereIn, insertRow, updateRow, deleteRowById, deleteRowsWhereEquals,
|
|
} from '../crud'
|
|
import type { ChecklistItemDef, ChecklistResponse } from '../../../src/db/types'
|
|
|
|
export const listChecklistItemDefsForPhaseTemplate = (phaseTemplateId: number): ChecklistItemDef[] => {
|
|
const rows = getRowsWhereEquals<ChecklistItemDef>('checklistItemDefs', 'phaseTemplateId', phaseTemplateId)
|
|
return rows.sort((a, b) => a.order - b.order)
|
|
}
|
|
|
|
/** Bulk-Variante für Berichte über mehrere Phasentypen hinweg (Assignment-Report-PDF, Gesamtprotokoll). */
|
|
export const listChecklistItemDefsForPhaseTemplates = (phaseTemplateIds: number[]): ChecklistItemDef[] =>
|
|
getRowsWhereIn<ChecklistItemDef>('checklistItemDefs', 'phaseTemplateId', phaseTemplateIds).sort((a, b) => a.order - b.order)
|
|
|
|
export const addChecklistItemDef = (def: Omit<ChecklistItemDef, 'id'>): number => insertRow('checklistItemDefs', def)
|
|
export const updateChecklistItemDef = (id: number, patch: Partial<ChecklistItemDef>): number =>
|
|
updateRow('checklistItemDefs', id, patch)
|
|
|
|
/** Räumt zugehörige `checklistResponses` mit auf — gleiches Verteidigungs-Prinzip wie `deleteFeedbackCriterionItem`. */
|
|
export function deleteChecklistItemDef(id: number): void {
|
|
deleteRowsWhereEquals('checklistResponses', 'checklistItemId', id)
|
|
deleteRowById('checklistItemDefs', id)
|
|
}
|
|
|
|
/** Cascade-Baustein für `deletePhaseTemplate`/`deleteAssignmentType` — löscht alle Checklisten-Punkte samt Antworten einer Phase. */
|
|
export function deleteChecklistItemDefsForPhaseTemplate(phaseTemplateId: number): void {
|
|
for (const def of listChecklistItemDefsForPhaseTemplate(phaseTemplateId)) {
|
|
deleteChecklistItemDef(def.id!)
|
|
}
|
|
}
|
|
|
|
export const listChecklistResponsesForMeeting = (meetingInstanceId: number): ChecklistResponse[] =>
|
|
getRowsWhereEquals<ChecklistResponse>('checklistResponses', 'meetingInstanceId', meetingInstanceId)
|
|
|
|
/** Bulk-Variante für Berichte über mehrere Meetings hinweg (Assignment-Report-PDF, Gesamtprotokoll). */
|
|
export const listChecklistResponsesForMeetings = (meetingInstanceIds: number[]): ChecklistResponse[] =>
|
|
getRowsWhereIn<ChecklistResponse>('checklistResponses', 'meetingInstanceId', meetingInstanceIds)
|
|
|
|
/**
|
|
* Upsert per Komposit-Schlüssel (meetingInstanceId, checklistItemId, instituteeId ?? null), gleiches
|
|
* Find-or-Insert-Muster wie `setAssessmentScore`/`saveAssessmentNote` in MeetingView.tsx. `criterionItemId`
|
|
* überschreibt pro Antwort individuell die Konfigurations-Vorgabe (`ChecklistItemDef.linkedCriterionItemId`)
|
|
* — siehe CLAUDE.md „Individuelle Kriterium-Zuordnung pro Checklisten-Antwort".
|
|
*/
|
|
export function upsertChecklistResponse(input: {
|
|
meetingInstanceId: number
|
|
instituteeId?: number
|
|
checklistItemId: number
|
|
rating: ChecklistResponse['rating']
|
|
note: string
|
|
criterionItemId?: number | null
|
|
criterionOverride?: boolean
|
|
}): number {
|
|
const existing = getAllRows<ChecklistResponse>('checklistResponses').find(r =>
|
|
r.meetingInstanceId === input.meetingInstanceId &&
|
|
r.checklistItemId === input.checklistItemId &&
|
|
(r.instituteeId ?? null) === (input.instituteeId ?? null),
|
|
)
|
|
const row = {
|
|
rating: input.rating,
|
|
note: input.note,
|
|
criterionItemId: input.criterionItemId,
|
|
criterionOverride: input.criterionOverride,
|
|
}
|
|
if (existing?.id) {
|
|
updateRow('checklistResponses', existing.id, row)
|
|
return existing.id
|
|
}
|
|
return insertRow('checklistResponses', { ...input, ...row })
|
|
}
|