232 lines
8.4 KiB
JavaScript
232 lines
8.4 KiB
JavaScript
export function createRecipesEditorController({
|
|
notyf,
|
|
getCurrentDispenserType,
|
|
setCurrentDispenserType,
|
|
getComponentsCache,
|
|
ensureComponentsLoaded,
|
|
setSelectedDispenser,
|
|
setSelectedPeriod,
|
|
setSelectedRecipe,
|
|
resetDeletedEntities,
|
|
setUnloadingLinkBroken,
|
|
initializeUnloadingLinkButton,
|
|
updateTripPercentFieldState,
|
|
setDryMatterMode,
|
|
loadIngredients,
|
|
loadUnloadingGroups,
|
|
showRecipeEdit,
|
|
}) {
|
|
function resetCreationForm() {
|
|
const recipeForm = document.getElementById("recipeForm");
|
|
if (recipeForm) recipeForm.reset();
|
|
|
|
const ingredientsTableBody = document.getElementById("ingredientsTableBody");
|
|
if (ingredientsTableBody) ingredientsTableBody.innerHTML = "";
|
|
|
|
const unloadingGroupsTableBody = document.getElementById("unloadingGroupsTableBody");
|
|
if (unloadingGroupsTableBody) unloadingGroupsTableBody.innerHTML = "";
|
|
|
|
updateTripPercentFieldState();
|
|
resetDeletedEntities();
|
|
|
|
const tripPercent = document.getElementById("tripPercent");
|
|
if (tripPercent) tripPercent.value = 100;
|
|
|
|
const totalWeightIngredients = document.getElementById("totalWeightIngredients");
|
|
if (totalWeightIngredients) totalWeightIngredients.textContent = "0";
|
|
|
|
const totalTripWeight = document.getElementById("totalTripWeight");
|
|
if (totalTripWeight) totalTripWeight.textContent = "0";
|
|
|
|
const totalDryMatterPerHead = document.getElementById("totalDryMatterPerHead");
|
|
if (totalDryMatterPerHead) totalDryMatterPerHead.textContent = "0";
|
|
|
|
const totalWeightPerHead = document.getElementById("totalWeightPerHead");
|
|
if (totalWeightPerHead) totalWeightPerHead.textContent = "0";
|
|
}
|
|
|
|
async function loadComponentsForMill() {
|
|
try {
|
|
await ensureComponentsLoaded();
|
|
const select = document.getElementById("targetComponentSelect");
|
|
if (!select) return;
|
|
|
|
const components = Array.isArray(getComponentsCache()) ? getComponentsCache() : [];
|
|
const currentValue = select.value;
|
|
select.innerHTML = `
|
|
<option value="">Выберите компонент...</option>
|
|
${components.map((component) => `<option value="${component.id}">${component.name}</option>`).join("")}
|
|
`;
|
|
if (currentValue) {
|
|
select.value = currentValue;
|
|
}
|
|
} catch (error) {
|
|
console.error("Ошибка при загрузке компонентов для кормоцеха:", error);
|
|
}
|
|
}
|
|
|
|
function toggleUnloadingBlocks() {
|
|
const isMill = getCurrentDispenserType() === "mill";
|
|
const unloadingGroupsCard = document.getElementById("unloadingGroupsCard");
|
|
const componentSelectionCard = document.getElementById("componentSelectionCard");
|
|
|
|
if (unloadingGroupsCard) unloadingGroupsCard.style.display = "block";
|
|
if (componentSelectionCard) {
|
|
componentSelectionCard.style.display = isMill ? "block" : "none";
|
|
}
|
|
|
|
if (isMill) {
|
|
loadComponentsForMill();
|
|
}
|
|
}
|
|
|
|
async function loadRecipeDetails(recipeId, options = {}) {
|
|
try {
|
|
const response = await fetch(`/api/recipes/${recipeId}`);
|
|
if (!response.ok) throw new Error("Ошибка при загрузке данных рецепта");
|
|
let recipe = await response.json();
|
|
|
|
if (!options.skipPlanOverlayFlags) {
|
|
const planDate =
|
|
options.planDate ||
|
|
globalThis.WespDailyPlanPanel?.getSelectedPlanDate?.() ||
|
|
new Date().toISOString().slice(0, 10);
|
|
try {
|
|
const overlayResp = await fetch(
|
|
`/api/recipes/${recipeId}?date=${encodeURIComponent(planDate)}`
|
|
);
|
|
if (overlayResp.ok) {
|
|
const overlay = await overlayResp.json();
|
|
const ingById = new Map(
|
|
(overlay.ingredients || []).map((ing) => [String(ing.id), ing])
|
|
);
|
|
recipe = {
|
|
...recipe,
|
|
ingredients: (recipe.ingredients || []).map((ing) => {
|
|
const overlayIng = ingById.get(String(ing.id));
|
|
if (!overlayIng) return ing;
|
|
return {
|
|
...ing,
|
|
skippedToday: Boolean(overlayIng.skippedToday),
|
|
adjustedToday: Boolean(overlayIng.adjustedToday),
|
|
replacedToday: Boolean(overlayIng.replacedToday),
|
|
};
|
|
}),
|
|
};
|
|
const groups = recipe.unloading_groups || recipe.unloadingGroups || [];
|
|
const grpById = new Map(
|
|
(overlay.unloadingGroups || overlay.unloading_groups || []).map((group) => [
|
|
String(group.id),
|
|
group,
|
|
])
|
|
);
|
|
const mergedGroups = groups.map((group) => {
|
|
const overlayGroup = grpById.get(String(group.id));
|
|
if (!overlayGroup) return group;
|
|
return { ...group, skippedToday: Boolean(overlayGroup.skippedToday) };
|
|
});
|
|
recipe.unloading_groups = mergedGroups;
|
|
recipe.unloadingGroups = mergedGroups;
|
|
}
|
|
} catch (overlayError) {
|
|
console.warn("Не удалось загрузить флаги плана для редактора рецепта:", overlayError);
|
|
}
|
|
}
|
|
|
|
resetDeletedEntities();
|
|
|
|
const recipeNameInput = document.getElementById("recipeName");
|
|
if (recipeNameInput) recipeNameInput.value = recipe.name || "";
|
|
const headsCountInput = document.getElementById("headsCount");
|
|
if (headsCountInput) {
|
|
const heads =
|
|
recipe.heads_count ??
|
|
recipe.headsPerTrip ??
|
|
recipe.heads_per_trip ??
|
|
"";
|
|
headsCountInput.value = heads === "" || heads == null ? "" : String(heads);
|
|
}
|
|
const mixingTimeInput = document.getElementById("mixingTime");
|
|
if (mixingTimeInput) {
|
|
const mt = recipe.mixing_time ?? recipe.mixingTime;
|
|
mixingTimeInput.value = mt === "" || mt == null ? "" : String(mt);
|
|
}
|
|
const tripPercentInput = document.getElementById("tripPercent");
|
|
if (tripPercentInput) {
|
|
const tp = recipe.trip_percent ?? recipe.tripPercent;
|
|
tripPercentInput.value = tp === "" || tp == null ? 100 : String(tp);
|
|
}
|
|
|
|
const ingredientsTableBody = document.getElementById("ingredientsTableBody");
|
|
if (ingredientsTableBody) ingredientsTableBody.innerHTML = "";
|
|
const unloadingGroupsTableBody = document.getElementById("unloadingGroupsTableBody");
|
|
if (unloadingGroupsTableBody) unloadingGroupsTableBody.innerHTML = "";
|
|
|
|
setUnloadingLinkBroken(recipe.unloading_link_broken || false);
|
|
initializeUnloadingLinkButton();
|
|
updateTripPercentFieldState();
|
|
|
|
setDryMatterMode(!!recipe.dry_matter_locked);
|
|
toggleUnloadingBlocks();
|
|
updateTripPercentFieldState();
|
|
|
|
await loadIngredients(recipe.ingredients);
|
|
const unloadingGroups = recipe.unloading_groups || recipe.unloadingGroups || [];
|
|
await loadUnloadingGroups(unloadingGroups);
|
|
|
|
if (getCurrentDispenserType() === "mill") {
|
|
const targetComponentSelect = document.getElementById("targetComponentSelect");
|
|
if (targetComponentSelect) {
|
|
targetComponentSelect.value = "";
|
|
if (recipe.target_component_id) {
|
|
targetComponentSelect.value = recipe.target_component_id;
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error("Ошибка при загрузке данных рецепта:", error);
|
|
notyf.error("Ошибка при загрузке данных рецепта");
|
|
}
|
|
}
|
|
|
|
async function createNewRecipeForMill(dispenserId) {
|
|
try {
|
|
setSelectedDispenser(dispenserId);
|
|
setSelectedPeriod(null);
|
|
setSelectedRecipe(null);
|
|
setCurrentDispenserType("mill");
|
|
|
|
resetCreationForm();
|
|
toggleUnloadingBlocks();
|
|
showRecipeEdit(true);
|
|
setDryMatterMode(false);
|
|
} catch (error) {
|
|
console.error("Ошибка в createNewRecipeForMill:", error);
|
|
notyf.error("Ошибка при создании рецепта");
|
|
}
|
|
}
|
|
|
|
async function createNewRecipe(periodId) {
|
|
try {
|
|
setSelectedPeriod(periodId);
|
|
setSelectedRecipe(null);
|
|
|
|
resetCreationForm();
|
|
toggleUnloadingBlocks();
|
|
showRecipeEdit(true);
|
|
setDryMatterMode(false);
|
|
} catch (error) {
|
|
console.error("Ошибка в createNewRecipe:", error);
|
|
notyf.error("Ошибка при создании рейса");
|
|
}
|
|
}
|
|
|
|
return {
|
|
toggleUnloadingBlocks,
|
|
loadComponentsForMill,
|
|
loadRecipeDetails,
|
|
createNewRecipeForMill,
|
|
createNewRecipe,
|
|
};
|
|
}
|