feat(cupang): 센터 즉시 추가·대화상자 센터 버튼 선택
- ③ 센터 분배: 목록에서 센터를 고르는 즉시 추가된다. "+ 센터 추가" 버튼 제거. 고른 뒤 선택값을 비워 같은 센터를 다시 고를 수 있게 한다. - 담기 대화상자: 센터 select 를 추가된 센터 버튼 목록으로 바꿔 한 번에 대상을 고른다(현재 대상은 검은 버튼 + aria-pressed). tests/js: 센터 추가를 change 이벤트로, 대화상자 센터 버튼 표시·전환· 선택한 센터로 담기는지까지 검증. 전체 통과. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
@@ -87,13 +87,13 @@
|
|||||||
등록된 입고센터가 없습니다. <a href="/cupang/centers">입고센터 관리</a>에서 먼저 센터를 추가하세요.
|
등록된 입고센터가 없습니다. <a href="/cupang/centers">입고센터 관리</a>에서 먼저 센터를 추가하세요.
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="cpg-inline-form cpg-center-pick">
|
<div class="cpg-center-pick">
|
||||||
<select class="erp-select" id="cpg-center-pick">
|
<select class="erp-select" id="cpg-center-pick" aria-label="센터 추가">
|
||||||
|
<option value="">— 센터를 고르면 바로 추가 —</option>
|
||||||
{% for c in centers %}
|
{% for c in centers %}
|
||||||
<option value="{{ c.id }}">{{ c.name }}</option>
|
<option value="{{ c.id }}">{{ c.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<button type="button" class="erp-btn erp-btn-primary" id="cpg-center-add">+ 센터 추가</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="cpg-dist-list" id="cpg-dist-list"></div>
|
<div class="cpg-dist-list" id="cpg-dist-list"></div>
|
||||||
<p class="erp-muted" id="cpg-dist-empty">추가한 센터가 여기에 표시됩니다.</p>
|
<p class="erp-muted" id="cpg-dist-empty">추가한 센터가 여기에 표시됩니다.</p>
|
||||||
@@ -108,8 +108,8 @@
|
|||||||
<div class="cpg-modal-box" role="dialog" aria-modal="true" aria-labelledby="cpg-dlg-title">
|
<div class="cpg-modal-box" role="dialog" aria-modal="true" aria-labelledby="cpg-dlg-title">
|
||||||
<h3 id="cpg-dlg-title">센터에 담기</h3>
|
<h3 id="cpg-dlg-title">센터에 담기</h3>
|
||||||
<p class="cpg-dlg-item" id="cpg-dlg-item"></p>
|
<p class="cpg-dlg-item" id="cpg-dlg-item"></p>
|
||||||
<label class="erp-field"><span>센터</span>
|
<div class="erp-field"><span>센터</span>
|
||||||
<select class="erp-select" id="cpg-dlg-center"></select></label>
|
<div class="cpg-dlg-centers" id="cpg-dlg-centers" role="group" aria-label="담을 센터"></div></div>
|
||||||
<label class="erp-field"><span>박스 수량</span>
|
<label class="erp-field"><span>박스 수량</span>
|
||||||
<input class="erp-input" type="number" id="cpg-dlg-qty" min="1" step="1" /></label>
|
<input class="erp-input" type="number" id="cpg-dlg-qty" min="1" step="1" /></label>
|
||||||
<p class="erp-muted" id="cpg-dlg-hint"></p>
|
<p class="erp-muted" id="cpg-dlg-hint"></p>
|
||||||
@@ -146,10 +146,10 @@
|
|||||||
var distCard = document.querySelector(".cpg-dist-card");
|
var distCard = document.querySelector(".cpg-dist-card");
|
||||||
var distEmpty = document.getElementById("cpg-dist-empty");
|
var distEmpty = document.getElementById("cpg-dist-empty");
|
||||||
var centerPick = document.getElementById("cpg-center-pick");
|
var centerPick = document.getElementById("cpg-center-pick");
|
||||||
var centerAdd = document.getElementById("cpg-center-add");
|
|
||||||
var dlg = document.getElementById("cpg-dlg");
|
var dlg = document.getElementById("cpg-dlg");
|
||||||
var dlgItem = document.getElementById("cpg-dlg-item");
|
var dlgItem = document.getElementById("cpg-dlg-item");
|
||||||
var dlgCenter = document.getElementById("cpg-dlg-center");
|
var dlgCenters = document.getElementById("cpg-dlg-centers");
|
||||||
|
var dlgCenterId = null; // 대화상자에서 고른 센터
|
||||||
var dlgQty = document.getElementById("cpg-dlg-qty");
|
var dlgQty = document.getElementById("cpg-dlg-qty");
|
||||||
var dlgHint = document.getElementById("cpg-dlg-hint");
|
var dlgHint = document.getElementById("cpg-dlg-hint");
|
||||||
var dlgOk = document.getElementById("cpg-dlg-ok");
|
var dlgOk = document.getElementById("cpg-dlg-ok");
|
||||||
@@ -435,10 +435,8 @@
|
|||||||
|
|
||||||
pending = { key: key };
|
pending = { key: key };
|
||||||
dlgItem.textContent = (labels[key] || key) + " — 잔여 " + remain + "박스 (" + (remain * (units[key] || 0)) + "개)";
|
dlgItem.textContent = (labels[key] || key) + " — 잔여 " + remain + "박스 (" + (remain * (units[key] || 0)) + "개)";
|
||||||
dlgCenter.innerHTML = openCenters.map(function (cid) {
|
dlgCenterId = String(centerId != null ? centerId : openCenters[0]);
|
||||||
return '<option value="' + esc(cid) + '"' + (String(cid) === String(centerId) ? " selected" : "") + ">" +
|
renderDialogCenters();
|
||||||
esc(centerName(cid)) + "</option>";
|
|
||||||
}).join("");
|
|
||||||
dlgQty.max = remain;
|
dlgQty.max = remain;
|
||||||
dlgQty.value = key.indexOf("m:") === 0 ? 1 : remain;
|
dlgQty.value = key.indexOf("m:") === 0 ? 1 : remain;
|
||||||
dlgHint.textContent = "1박스 = " + (units[key] || 0) + "개 · 최대 " + remain + "박스";
|
dlgHint.textContent = "1박스 = " + (units[key] || 0) + "개 · 최대 " + remain + "박스";
|
||||||
@@ -447,12 +445,28 @@
|
|||||||
dlgQty.select();
|
dlgQty.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDialogCenters() {
|
||||||
|
dlgCenters.innerHTML = openCenters.map(function (cid) {
|
||||||
|
var on = String(cid) === String(dlgCenterId);
|
||||||
|
return '<button type="button" class="erp-btn ' + (on ? "erp-btn-primary" : "erp-btn-outline") +
|
||||||
|
' cpg-dlg-center-btn" data-center="' + esc(cid) + '"' + (on ? ' aria-pressed="true"' : '') + ">" +
|
||||||
|
esc(centerName(cid)) + "</button>";
|
||||||
|
}).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
dlgCenters.addEventListener("click", function (e) {
|
||||||
|
var btn = e.target.closest(".cpg-dlg-center-btn");
|
||||||
|
if (!btn) return;
|
||||||
|
dlgCenterId = btn.getAttribute("data-center");
|
||||||
|
renderDialogCenters();
|
||||||
|
});
|
||||||
|
|
||||||
function closeDialog() { dlg.hidden = true; pending = null; }
|
function closeDialog() { dlg.hidden = true; pending = null; }
|
||||||
|
|
||||||
function commitDialog(all) {
|
function commitDialog(all) {
|
||||||
if (!pending) return;
|
if (!pending) return;
|
||||||
var key = pending.key;
|
var key = pending.key;
|
||||||
var cid = dlgCenter.value;
|
var cid = dlgCenterId;
|
||||||
var want = all ? remainFor(key) : parseInt(dlgQty.value, 10);
|
var want = all ? remainFor(key) : parseInt(dlgQty.value, 10);
|
||||||
var got = addAlloc(cid, key, want);
|
var got = addAlloc(cid, key, want);
|
||||||
closeDialog();
|
closeDialog();
|
||||||
@@ -629,13 +643,16 @@
|
|||||||
if (badges[1]) badges[1].textContent = pieces + "개";
|
if (badges[1]) badges[1].textContent = pieces + "개";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (centerAdd) {
|
if (centerPick) {
|
||||||
centerAdd.addEventListener("click", function () {
|
// 목록에서 센터를 고르는 즉시 ③ 에 추가한다(별도 추가 버튼 없음).
|
||||||
|
centerPick.addEventListener("change", function () {
|
||||||
var cid = centerPick.value;
|
var cid = centerPick.value;
|
||||||
|
centerPick.value = ""; // 같은 센터를 다시 고를 수 있게 초기화
|
||||||
if (!cid) return;
|
if (!cid) return;
|
||||||
if (openCenters.indexOf(cid) >= 0) { msg.textContent = "이미 추가된 센터입니다."; return; }
|
if (openCenters.indexOf(cid) >= 0) { msg.textContent = "이미 추가된 센터입니다."; return; }
|
||||||
openCenters.push(cid);
|
openCenters.push(cid);
|
||||||
renderDist();
|
renderDist();
|
||||||
|
msg.textContent = centerName(cid) + " 추가됨";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829g" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260829h" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
+11
-1
@@ -658,7 +658,7 @@ body.cpg-dragging { cursor: grabbing; user-select: none; }
|
|||||||
}
|
}
|
||||||
.cpg-dist-sum { display: inline-flex; align-items: center; gap: 6px; }
|
.cpg-dist-sum { display: inline-flex; align-items: center; gap: 6px; }
|
||||||
.cpg-dist-close { padding: 0 6px; line-height: 1.5; }
|
.cpg-dist-close { padding: 0 6px; line-height: 1.5; }
|
||||||
.cpg-center-pick { display: flex; gap: 8px; margin-bottom: 10px; }
|
.cpg-center-pick { margin-bottom: 10px; }
|
||||||
.cpg-center-pick .erp-select { flex: 1 1 auto; min-width: 0; }
|
.cpg-center-pick .erp-select { flex: 1 1 auto; min-width: 0; }
|
||||||
.cpg-dist-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
.cpg-dist-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
||||||
.cpg-dist-item {
|
.cpg-dist-item {
|
||||||
@@ -695,3 +695,13 @@ body.cpg-dragging { cursor: grabbing; user-select: none; }
|
|||||||
/* 드래그 중일 때 ③ 영역을 강조 — 어디에 놓아야 하는지 보이게 */
|
/* 드래그 중일 때 ③ 영역을 강조 — 어디에 놓아야 하는지 보이게 */
|
||||||
.cpg-dist-card.is-drop-ready { outline: 2px dashed var(--color-rich-black); outline-offset: 2px; }
|
.cpg-dist-card.is-drop-ready { outline: 2px dashed var(--color-rich-black); outline-offset: 2px; }
|
||||||
.cpg-dist-card.is-drop-ready .cpg-dist-center { border-color: var(--color-midtone-gray); }
|
.cpg-dist-card.is-drop-ready .cpg-dist-center { border-color: var(--color-midtone-gray); }
|
||||||
|
|
||||||
|
/* 대화상자 센터 버튼 목록 */
|
||||||
|
.cpg-dlg-centers {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
max-height: 132px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.cpg-dlg-center-btn { padding: 4px 12px; }
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ function dragCardTo(card, target) {
|
|||||||
// ── ③ 센터는 추가한 것만 표시 ─────────────────────
|
// ── ③ 센터는 추가한 것만 표시 ─────────────────────
|
||||||
check("초기 센터 패널 없음", $$(".cpg-dist-center").length === 0);
|
check("초기 센터 패널 없음", $$(".cpg-dist-center").length === 0);
|
||||||
$("#cpg-center-pick").value = "1";
|
$("#cpg-center-pick").value = "1";
|
||||||
$("#cpg-center-add").click();
|
fire($("#cpg-center-pick"), "change");
|
||||||
check("센터 추가 후 1개 표시", $$(".cpg-dist-center").length === 1, String($$(".cpg-dist-center").length));
|
check("센터 추가 후 1개 표시", $$(".cpg-dist-center").length === 1, String($$(".cpg-dist-center").length));
|
||||||
check("추가한 센터 이름", text(".cpg-dist-center strong") === "대구3", text(".cpg-dist-center strong"));
|
check("추가한 센터 이름", text(".cpg-dist-center strong") === "대구3", text(".cpg-dist-center strong"));
|
||||||
|
|
||||||
@@ -97,7 +97,10 @@ function dragCardTo(card, target) {
|
|||||||
check("드롭 후 고스트 제거", !$(".cpg-drag-ghost"));
|
check("드롭 후 고스트 제거", !$(".cpg-drag-ghost"));
|
||||||
check("드롭하면 대화상자가 열린다", $("#cpg-dlg").hidden === false);
|
check("드롭하면 대화상자가 열린다", $("#cpg-dlg").hidden === false);
|
||||||
check("대화상자에 잔여/개수 표시", text("#cpg-dlg-item").includes("잔여 2박스 (16개)"), text("#cpg-dlg-item"));
|
check("대화상자에 잔여/개수 표시", text("#cpg-dlg-item").includes("잔여 2박스 (16개)"), text("#cpg-dlg-item"));
|
||||||
check("대화상자 센터 = 드롭한 센터", $("#cpg-dlg-center").value === "1");
|
check("대화상자에 센터 버튼 표시", $$(".cpg-dlg-center-btn").length === 1, String($$(".cpg-dlg-center-btn").length));
|
||||||
|
check("드롭한 센터 버튼이 선택됨",
|
||||||
|
$(".cpg-dlg-center-btn[aria-pressed='true']").getAttribute("data-center") === "1",
|
||||||
|
$(".cpg-dlg-center-btn[aria-pressed='true']").getAttribute("data-center"));
|
||||||
|
|
||||||
// 1박스만 담기
|
// 1박스만 담기
|
||||||
$("#cpg-dlg-qty").value = "1";
|
$("#cpg-dlg-qty").value = "1";
|
||||||
@@ -153,7 +156,7 @@ function dragCardTo(card, target) {
|
|||||||
|
|
||||||
// ── 드롭 실패 경로 방어 ───────────────────────────
|
// ── 드롭 실패 경로 방어 ───────────────────────────
|
||||||
$("#cpg-center-pick").value = "2";
|
$("#cpg-center-pick").value = "2";
|
||||||
$("#cpg-center-add").click();
|
fire($("#cpg-center-pick"), "change");
|
||||||
check("센터 다시 추가", $$(".cpg-dist-center").length === 1, String($$(".cpg-dist-center").length));
|
check("센터 다시 추가", $$(".cpg-dist-center").length === 1, String($$(".cpg-dist-center").length));
|
||||||
|
|
||||||
// (1) 패널이 아닌 ③ 카드 여백에 놓아도 센터가 하나면 그 센터로
|
// (1) 패널이 아닌 ③ 카드 여백에 놓아도 센터가 하나면 그 센터로
|
||||||
@@ -169,6 +172,24 @@ function dragCardTo(card, target) {
|
|||||||
check("③ 밖에 놓으면 담기지 않는다", $("#cpg-dlg").hidden === true && $$(".cpg-dist-item").length === 0);
|
check("③ 밖에 놓으면 담기지 않는다", $("#cpg-dlg").hidden === true && $$(".cpg-dist-item").length === 0);
|
||||||
check("③ 밖 드롭 안내 메시지", text("#cpg-calc-msg").includes("센터 위에 놓아야"), text("#cpg-calc-msg"));
|
check("③ 밖 드롭 안내 메시지", text("#cpg-calc-msg").includes("센터 위에 놓아야"), text("#cpg-calc-msg"));
|
||||||
|
|
||||||
|
// (3) 대화상자에서 센터 버튼으로 대상 변경
|
||||||
|
$("#cpg-center-pick").value = "1";
|
||||||
|
fire($("#cpg-center-pick"), "change");
|
||||||
|
check("센터 2개 표시", $$(".cpg-dist-center").length === 2, String($$(".cpg-dist-center").length));
|
||||||
|
$(".cpg-sum-prod.is-draggable").click();
|
||||||
|
check("센터 2개 → 버튼 2개", $$(".cpg-dlg-center-btn").length === 2);
|
||||||
|
const other = $$(".cpg-dlg-center-btn").filter(b => b.getAttribute("aria-pressed") !== "true")[0];
|
||||||
|
const otherId = other.getAttribute("data-center");
|
||||||
|
other.click();
|
||||||
|
check("버튼 클릭으로 센터 변경",
|
||||||
|
$(".cpg-dlg-center-btn[aria-pressed='true']").getAttribute("data-center") === otherId);
|
||||||
|
$("#cpg-dlg-qty").value = "1";
|
||||||
|
$("#cpg-dlg-ok").click();
|
||||||
|
const target = $('[data-drop-for="' + otherId + '"]');
|
||||||
|
check("선택한 센터에 담긴다", target.querySelectorAll(".cpg-dist-item").length === 1);
|
||||||
|
target.querySelector(".cpg-dist-del").click();
|
||||||
|
$(".cpg-dist-close").click();
|
||||||
|
|
||||||
// (3) 드래그 없이 클릭한 경우
|
// (3) 드래그 없이 클릭한 경우
|
||||||
$(".cpg-sum-prod.is-draggable").click();
|
$(".cpg-sum-prod.is-draggable").click();
|
||||||
check("클릭 대체 경로 동작", $("#cpg-dlg").hidden === false);
|
check("클릭 대체 경로 동작", $("#cpg-dlg").hidden === false);
|
||||||
|
|||||||
Reference in New Issue
Block a user