/* ============================================================
Заявка на замер — менеджер создаёт, замерщику в инбокс
============================================================ */
const MeasurementRequest = (function () {
let root = null;
let state = {
client_name: "",
client_phone: "",
address: "",
assigned_to_tg_id: "",
notes: "",
};
let measurers = [];
function mount(container) {
root = container;
document.body.classList.remove("has-bottom-nav");
const oldNav = document.getElementById("bottom-nav");
if (oldNav) oldNav.remove();
state = { client_name: "", client_phone: "", address: "", assigned_to_tg_id: "", notes: "" };
render();
loadMeasurers();
}
function render() {
if (!root) return;
root.innerHTML = "";
root.appendChild(headerEl("Новая заявка на замер", "#/"));
const form = el(`
`);
root.appendChild(form);
bindInputs(form);
form.querySelector("#submit").addEventListener("click", () => onSubmit(form));
}
function bindInputs(node) {
node.querySelectorAll("[data-bind]").forEach(inp => {
inp.addEventListener("input", e => {
state[e.target.dataset.bind] = e.target.value;
});
inp.addEventListener("change", e => {
state[e.target.dataset.bind] = e.target.value;
});
});
}
async function loadMeasurers() {
try {
const res = await fetch(`${BACKEND_URL}/api/staff_list`, {
method: "POST",
body: JSON.stringify({ initData: tg?.initData || "", role: "measurer" }),
});
const data = await res.json();
measurers = data.staff || [];
const sel = document.getElementById("measurerSelect");
const hint = document.getElementById("measurerHint");
if (!sel) return;
if (!measurers.length) {
sel.innerHTML = ``;
sel.disabled = true;
if (hint) hint.textContent = "Сначала выдайте кому-нибудь роль measurer через /grant_role";
return;
}
sel.disabled = false;
sel.innerHTML = `` +
measurers.map(m => ``).join("");
} catch (e) {
const sel = document.getElementById("measurerSelect");
if (sel) sel.innerHTML = ``;
}
}
async function onSubmit(form) {
const btn = form.querySelector("#submit");
const result = form.querySelector("#submitResult");
// Валидация
form.querySelector("#errName").textContent = "";
form.querySelector("#errPhone").textContent = "";
const name = (state.client_name || "").trim();
const phone = (state.client_phone || "").trim();
if (!name) {
form.querySelector("#errName").textContent = "Укажите имя клиента";
return;
}
if (phone.replace(/\D/g, "").length < 10) {
form.querySelector("#errPhone").textContent = "Слишком короткий номер";
return;
}
btn.disabled = true;
btn.innerHTML = ' создаём...';
result.innerHTML = "";
try {
const res = await fetch(`${BACKEND_URL}/api/measurement_request`, {
method: "POST",
body: JSON.stringify({
initData: tg?.initData || "",
client_name: name,
client_phone: phone,
address: state.address || "",
assigned_to_tg_id: state.assigned_to_tg_id || "",
notes: state.notes || "",
}),
});
const data = await res.json();
if (data.error) {
result.innerHTML = `
Ошибка: ${data.error}
`;
btn.disabled = false;
btn.textContent = "Попробовать снова";
return;
}
haptic && haptic("success");
const assignedTo = state.assigned_to_tg_id
? measurers.find(m => String(m.tg_id) === String(state.assigned_to_tg_id))
: null;
result.innerHTML = `
${ICONS.check}
Заявка создана
ID #${(data.id || "").slice(0, 6)}${assignedTo ? " · Замерщик уведомлён в Telegram" : " · Без назначения"}
`;
form.querySelector("#newOne")?.addEventListener("click", () => mount(root));
form.querySelector("#toHome")?.addEventListener("click", () => {
location.hash = "";
location.reload();
});
} catch (e) {
result.innerHTML = `Сеть: ${e.message}
`;
btn.disabled = false;
btn.textContent = "Попробовать снова";
}
}
function headerEl(title, backHref) {
const h = el(`
`);
h.querySelector(".podbor-back").addEventListener("click", () => {
if (backHref) location.hash = backHref;
else location.hash = "";
if (!location.hash) location.reload();
});
return h;
}
function escHtml(s) {
return String(s == null ? "" : s)
.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """);
}
return { mount };
})();