Files
site/apps/web/public/wesp/js/pages/lab-animal-profiles-modal.js
T

105 lines
4.5 KiB
JavaScript

(function (global) {
"use strict";
function escapeHtml(s) {
return String(s ?? "")
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
async function openLabAnimalProfilesModal() {
const resp = await fetch("/api/lab/animal-profiles");
const data = await resp.json().catch(() => ({}));
if (!resp.ok) {
global.WespZootechNotify?.createAdapter?.()?.error?.(data.message || "Ошибка загрузки профилей");
return;
}
const profiles = data.profiles || [];
const options = profiles
.map(
(p) =>
`<option value="${escapeHtml(p.id)}">${escapeHtml(p.label)} (${escapeHtml(p.rationType)})</option>`
)
.join("");
const html =
`<div class="lab-profiles-editor">` +
`<p class="small text-muted mb-2">Профили норм стада (зоотех). Выберите для просмотра или создайте новый.</p>` +
`<label class="form-label">Существующие</label>` +
`<select class="form-select mb-2" id="labProfilePick"><option value="">—</option>${options}</select>` +
`<div id="labProfileView" class="small mb-3 text-muted" hidden></div>` +
`<hr>` +
`<label class="form-label">Новый / редактирование</label>` +
`<input class="form-control form-control-sm mb-1" id="labProfileKey" placeholder="Ключ (beef_grow)">` +
`<input class="form-control form-control-sm mb-1" id="labProfileLabel" placeholder="Название">` +
`<select class="form-select form-select-sm mb-1" id="labProfileType">` +
`<option value="BEEF">Мясное</option><option value="DAIRY">Дойное</option></select>` +
`<textarea class="form-control form-control-sm" id="labProfileNorms" rows="4" placeholder='{"dry_matter":{"min":4000,"max":5000}}'></textarea>` +
`</div>`;
const ok = await global.WespDialog?.confirm?.(html, {
title: "Профили норм стада",
html: true,
confirmText: "Сохранить",
cancelText: "Закрыть",
});
if (!ok) return;
const pick = document.getElementById("labProfilePick")?.value;
const key = document.getElementById("labProfileKey")?.value?.trim();
const label = document.getElementById("labProfileLabel")?.value?.trim();
const rationType = document.getElementById("labProfileType")?.value || "BEEF";
let normsData = {};
try {
const raw = document.getElementById("labProfileNorms")?.value?.trim();
if (raw) normsData = JSON.parse(raw);
} catch (_) {
global.WespZootechNotify?.createAdapter?.()?.error?.("Некорректный JSON норм");
return;
}
if (!key || !label) {
global.WespZootechNotify?.createAdapter?.()?.error?.("Укажите ключ и название");
return;
}
const method = pick ? "PUT" : "POST";
const url = pick
? `/api/lab/animal-profiles/${encodeURIComponent(pick)}`
: "/api/lab/animal-profiles";
try {
const saveResp = await fetch(url, {
method,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ profileKey: key, label, rationType, normsData }),
});
const saveData = await saveResp.json();
if (!saveResp.ok) throw new Error(saveData.message || "Ошибка сохранения");
global.WespZootechNotify?.createAdapter?.()?.success?.("Профиль сохранён");
} catch (e) {
global.WespZootechNotify?.createAdapter?.()?.error?.(e.message, { fallback: "Не удалось сохранить профиль" });
}
}
document.addEventListener("change", (ev) => {
if (ev.target?.id !== "labProfilePick") return;
const id = ev.target.value;
const view = document.getElementById("labProfileView");
if (!id || !view) return;
fetch(`/api/lab/animal-profiles/${encodeURIComponent(id)}`)
.then((r) => r.json())
.then((p) => {
document.getElementById("labProfileKey").value = p.profileKey || "";
document.getElementById("labProfileLabel").value = p.label || "";
document.getElementById("labProfileType").value = p.rationType || "BEEF";
document.getElementById("labProfileNorms").value = JSON.stringify(p.normsData || {}, null, 2);
view.hidden = false;
view.textContent = `${p.profileKey} · ${p.rationType}`;
})
.catch(() => {});
});
global.openLabAnimalProfilesModal = openLabAnimalProfilesModal;
})(window);