import type { ClientPrefix, ClientPrefixInput } from "@/lib/types"; export interface PrefixRow { prefix: string; group_id: number; /** Raw input text; empty means "use the server default (100)". */ priority: string; } export interface PrefixEditorState { baseline: PrefixRow[]; rows: PrefixRow[]; } export type PrefixEditorAction = | { type: "reset"; prefixes: ClientPrefix[] } | { type: "add"; groupId: number } | { type: "remove"; index: number } | { type: "edit"; index: number; patch: Partial }; function fromServer(prefixes: ClientPrefix[]): PrefixRow[] { return prefixes.map((p) => ({ prefix: p.prefix, group_id: p.group_id, priority: String(p.priority) })); } export function initPrefixEditor(prefixes: ClientPrefix[]): PrefixEditorState { const rows = fromServer(prefixes); return { baseline: rows, rows }; } export function prefixEditorReducer(state: PrefixEditorState, action: PrefixEditorAction): PrefixEditorState { switch (action.type) { case "reset": return initPrefixEditor(action.prefixes); case "add": return { ...state, rows: [...state.rows, { prefix: "", group_id: action.groupId, priority: "" }] }; case "remove": return { ...state, rows: state.rows.filter((_, i) => i !== action.index) }; case "edit": return { ...state, rows: state.rows.map((row, i) => (i === action.index ? { ...row, ...action.patch } : row)), }; } } function sameRow(a: PrefixRow, b: PrefixRow): boolean { return a.prefix === b.prefix && a.group_id === b.group_id && a.priority === b.priority; } export function isDirty(state: PrefixEditorState): boolean { if (state.rows.length !== state.baseline.length) return true; return state.rows.some((row, i) => { const base = state.baseline[i]; return base === undefined || !sameRow(row, base); }); } export function firstProblem(rows: PrefixRow[]): string | null { for (const [i, row] of rows.entries()) { if (row.prefix.trim() === "") return `Row ${i + 1}: prefix is required.`; const priority = row.priority.trim(); if (priority !== "" && !/^\d+$/.test(priority)) return `Row ${i + 1}: priority must be a whole number.`; } return null; } export function toInputs(rows: PrefixRow[]): ClientPrefixInput[] { return rows.map((row) => { const input: ClientPrefixInput = { prefix: row.prefix.trim(), group_id: row.group_id }; const priority = row.priority.trim(); if (priority !== "") input.priority = Number(priority); return input; }); }