/** * Диалог «На какой срок…» для skip/replace/adjustment плана на день. */ (function (global) { function escapeHtml(value) { return String(value ?? "") .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """); } function weekEndIso(planDate) { const parts = String(planDate || "").split("-"); const d = new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2])); const jsDay = d.getDay(); const pyWeekday = jsDay === 0 ? 6 : jsDay - 1; d.setDate(d.getDate() + (6 - pyWeekday)); const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${y}-${m}-${day}`; } function todayIso() { const d = new Date(); return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; } function dismissOverlays(host, keepSelectors) { host.querySelectorAll(".zt-k-hub-plan-overlay").forEach((el) => { if (keepSelectors.some((sel) => el.matches(sel))) return; el.remove(); }); } /** * @param {object} options * @param {string} options.planDate YYYY-MM-DD * @param {string} [options.title] * @param {HTMLElement} [options.overlayHost] куда монтировать overlay * @param {string[]} [options.keepOverlays] селекторы overlay, которые не закрывать * @param {function} [options.onError] * @param {function} [options.beforeAppend] (overlay) => void — dismiss other overlays */ function promptSkipDuration(options) { const planDate = options.planDate || todayIso(); const title = options.title || "На какой срок исключить?"; const onError = options.onError || function () {}; const host = options.overlayHost || document.body; const keepOverlays = options.keepOverlays || []; return new Promise((resolve) => { const weekEnd = weekEndIso(planDate); const overlay = document.createElement("div"); overlay.className = "zt-k-hub-plan-overlay zt-k-hub-plan-skip-duration"; overlay.innerHTML = '"; if (typeof options.beforeAppend === "function") { options.beforeAppend(overlay); } else if (keepOverlays.length) { dismissOverlays(host, keepOverlays); } overlay.setAttribute("data-daily-plan-overlay", "1"); host.appendChild(overlay); const dateInput = overlay.querySelector("[data-skip-until-date]"); const finish = (value) => { if (overlay.isConnected) overlay.remove(); resolve(value); }; overlay.addEventListener("click", (event) => { if (event.target === overlay) finish(null); }); overlay.querySelector("[data-skip-duration-cancel]")?.addEventListener("click", () => finish(null)); overlay.querySelector("[data-skip-duration-confirm]")?.addEventListener("click", () => { const selected = overlay.querySelector('input[name="skip-duration"]:checked'); const mode = selected?.value || "today"; if (mode === "week") { finish({ duration: "week" }); return; } if (mode === "date") { const untilDate = dateInput?.value || planDate; if (untilDate < planDate) { onError("Дата окончания не может быть раньше начала"); return; } finish({ duration: "date", untilDate }); return; } finish({ duration: "today" }); }); }); } function skipDurationBody(planDate, extra, title, options) { return promptSkipDuration({ planDate, title, ...options }).then((choice) => { if (!choice) return null; return { date: planDate, ...choice, ...(extra || {}) }; }); } global.WespDailyPlanSkipDuration = { weekEndIso, todayIso, promptSkipDuration, skipDurationBody, escapeHtml, }; })(window);