shinkan-jinkendo/frontend/src/utils/comboPlanningMethodProfile.js

64 lines
2.0 KiB
JavaScript
Raw Normal View History

/** Effektives Ablaufprofil für Kombination im Coach/in der Planung */
/**
* Vereinigt slot_profiles_v1 aus Katalog und Planungs-Overlay (je slot_index).
* @param {unknown} catArr
* @param {unknown} planArr
*/
function mergeSlotProfilesV1(catArr, planArr) {
const c = Array.isArray(catArr) ? catArr : []
const p = Array.isArray(planArr) ? planArr : []
const byIx = new Map()
for (const r of c) {
if (!r || typeof r !== 'object') continue
const ix = Number(r.slot_index)
if (!Number.isFinite(ix)) continue
byIx.set(ix, { ...r })
}
for (const r of p) {
if (!r || typeof r !== 'object') continue
const ix = Number(r.slot_index)
if (!Number.isFinite(ix)) continue
const prev = byIx.get(ix) || {}
byIx.set(ix, { ...prev, ...r })
}
return [...byIx.entries()].sort((a, b) => a[0] - b[0]).map(([, row]) => row)
}
/**
* Katalog-Basis + optionaler Planungs-Snapshot.
* Wichtig: `planning_method_profile` darf nur **Überschreibungen** sein — nie den Katalog komplett ersetzen
* (sonst verschwinden Zeiten/Runden bei leerem Objekt oder Teil-Payload).
*/
export function effectiveComboMethodProfile(catalogDict, planningSnapshot) {
const cat =
catalogDict && typeof catalogDict === 'object' && !Array.isArray(catalogDict) ? { ...catalogDict } : {}
if (
planningSnapshot === null ||
planningSnapshot === undefined ||
typeof planningSnapshot !== 'object' ||
Array.isArray(planningSnapshot)
) {
return { ...cat }
}
const plan = planningSnapshot
const merged = { ...cat, ...plan }
if (Object.prototype.hasOwnProperty.call(plan, 'slot_profiles_v1')) {
merged.slot_profiles_v1 = mergeSlotProfilesV1(cat.slot_profiles_v1, plan.slot_profiles_v1)
}
return merged
}
export function comboPlanningProfileJsonForEditor(catalogDict, planningSnapshot) {
const o = effectiveComboMethodProfile(catalogDict, planningSnapshot)
try {
return JSON.stringify(Object.keys(o).length ? o : {})
} catch {
return '{}'
}
}