feat(cupang): 박스 계산 3열 작업공간 + 센터 분배 드래그

① 박스 계산: 제품명·수량만 입력(결과 열 제거). 수량 칸에서 Tab 은 다음
   행 수량으로 이동하고 마지막 행이면 새 행을 추가한다. Enter 는 계산.
② 박스 요약: 제품별 박스/자투리 혼합 박스 카드가 드래그 소스. 표시되는
   수치는 센터에 배분하고 남은 "잔여" 기준으로 실시간 갱신되며, KPI 는
   총 박스 / 센터 배분 / 미배분 잔여 3개로 바꿨다.
③ 센터 분배: 활성 입고센터(cupang_centers)만 표시. 카드를 끌어다 놓으면
   해당 센터에 1박스가 담기고, 박스 수량을 직접 입력할 수 있다(잔여를
   넘으면 자동으로 잘림). ✕ 로 빼면 잔여로 되돌아간다.

혼합 박스는 내용이 서로 달라 1장 = 1박스로 취급한다. 분배 내역은 화면
안에서만 유지(DB 저장 없음)하며, 재계산하면 근거가 바뀌므로 초기화한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-29 02:47:48 +09:00
parent fe344f9fda
commit 2de019a203
9 changed files with 401 additions and 153 deletions
+72
View File
@@ -577,3 +577,75 @@
stroke-width: 3px;
stroke-linejoin: round;
}
/* ── 박스 계산 3열 작업 영역 (① 계산 / ② 요약 / ③ 센터 분배) ── */
.cpg-calc3 {
display: grid;
grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.25fr) minmax(0, 0.9fr);
gap: 16px;
align-items: stretch;
}
.cpg-calc3 > .erp-card { margin-bottom: 0; display: flex; flex-direction: column; }
@media (max-width: 1500px) {
.cpg-calc3 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.cpg-calc3 > .cpg-dist-card { grid-column: 1 / -1; }
}
@media (max-width: 1000px) {
.cpg-calc3 { grid-template-columns: minmax(0, 1fr); }
.cpg-calc3 > .cpg-dist-card { grid-column: auto; }
}
/* ② 요약: 카드가 드래그 가능함을 알린다 */
.cpg-sum-prod[draggable="true"], .cpg-box-card[draggable="true"] { cursor: grab; }
.cpg-sum-prod[draggable="true"]:hover, .cpg-box-card[draggable="true"]:hover {
border-color: var(--color-rich-black);
}
.cpg-sum-prod.is-dragging, .cpg-box-card.is-dragging { opacity: .45; }
.cpg-sum-prod.is-done, .cpg-box-card.is-done { opacity: .5; }
/* ③ 센터 분배 */
.cpg-dist-list {
display: flex;
flex-direction: column;
gap: 10px;
overflow-y: auto;
max-height: min(72vh, 820px);
}
.cpg-dist-center {
border: 1px solid var(--color-subtle-ash);
border-radius: 10px;
padding: 10px 12px;
}
.cpg-dist-center.has-items { border-color: var(--color-rich-black); }
.cpg-dist-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 8px;
font-size: 14px;
}
.cpg-dist-drop {
border: 1.5px dashed var(--color-subtle-ash);
border-radius: 8px;
padding: 8px;
min-height: 52px;
transition: background .15s ease, border-color .15s ease;
}
.cpg-dist-drop.is-over {
border-color: var(--color-rich-black);
background: var(--color-ghost-gray);
}
.cpg-dist-hint { font-size: 12px; color: var(--color-midtone-gray); }
.cpg-dist-center.has-items .cpg-dist-hint { display: none; }
.cpg-dist-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.cpg-dist-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
}
.cpg-dist-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpg-dist-qty { width: 62px; min-width: 0; text-align: right; padding: 2px 6px; }
.cpg-dist-unit { font-size: 12px; color: var(--color-midtone-gray); }
.cpg-dist-del { padding: 2px 8px; line-height: 1.4; }