feat(cupang): 선택일 출고 항목 hover 툴팁(제품명+수량, 커서 따라감)
- index sel_shipments 에 품목 요약(name/qty) 첨부 - 리스트 항목 hover 시 커서 왼쪽에 따라다니는 툴팁 표시 - 캐시 버전 m Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,14 @@ async def index(request: Request) -> HTMLResponse:
|
|||||||
s for s in shipments
|
s for s in shipments
|
||||||
if sel in (s.get("ship_date"), s.get("document_date"), s.get("center_arrival_date"))
|
if sel in (s.get("ship_date"), s.get("document_date"), s.get("center_arrival_date"))
|
||||||
]
|
]
|
||||||
|
# 각 묶음에 품목 요약(제품명/수량) 첨부 — hover 툴팁용
|
||||||
|
for s in sel_shipments:
|
||||||
|
full = store.get_shipment(shipment_id=s["id"])
|
||||||
|
s["items"] = [
|
||||||
|
{"name": ln.get("product_name_snapshot") or ln.get("product_code"),
|
||||||
|
"qty": ln.get("quantity", 0)}
|
||||||
|
for ln in (full.get("lines") if full else [])
|
||||||
|
]
|
||||||
|
|
||||||
cal = _calendar.Calendar(firstweekday=6) # 일요일 시작
|
cal = _calendar.Calendar(firstweekday=6) # 일요일 시작
|
||||||
weeks = cal.monthdatescalendar(year, month)
|
weeks = cal.monthdatescalendar(year, month)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530l" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530m" />{% 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=20260530l" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530m" />{% 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=20260530l" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530m" />{% 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=20260530l" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530m" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
@@ -109,4 +109,4 @@
|
|||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}<script src="/static/cupang.js?v=20260530l" defer></script>{% endblock %}
|
{% block scripts %}<script src="/static/cupang.js?v=20260530m" defer></script>{% endblock %}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530l" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530m" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
@@ -65,7 +65,8 @@
|
|||||||
<ul class="cpg-list">
|
<ul class="cpg-list">
|
||||||
{% for s in sel_shipments %}
|
{% for s in sel_shipments %}
|
||||||
<li class="cpg-list-item">
|
<li class="cpg-list-item">
|
||||||
<a href="/cupang/{{ s.id }}" class="cpg-list-link">
|
<a href="/cupang/{{ s.id }}" class="cpg-list-link cpg-hover-item"
|
||||||
|
data-items='{{ s.items | tojson }}'>
|
||||||
<div class="cpg-list-top">
|
<div class="cpg-list-top">
|
||||||
<strong>{{ s.center_name_snapshot or '센터 미지정' }}</strong>
|
<strong>{{ s.center_name_snapshot or '센터 미지정' }}</strong>
|
||||||
{% set badge = 'erp-badge-neutral' %}
|
{% set badge = 'erp-badge-neutral' %}
|
||||||
@@ -89,5 +90,55 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- hover 툴팁 (마우스 따라다님, 커서 왼쪽) -->
|
||||||
|
<div id="cpg-hover-tip" class="cpg-hover-tip" hidden></div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var tip = document.getElementById("cpg-hover-tip");
|
||||||
|
if (!tip) return;
|
||||||
|
|
||||||
|
function buildHtml(items) {
|
||||||
|
if (!items || !items.length) return '<div class="cpg-tip-empty">품목 없음</div>';
|
||||||
|
var html = "";
|
||||||
|
items.forEach(function (it) {
|
||||||
|
var d1 = document.createElement("div");
|
||||||
|
d1.className = "cpg-tip-row";
|
||||||
|
var n = document.createElement("span"); n.className = "cpg-tip-name"; n.textContent = it.name || "";
|
||||||
|
var q = document.createElement("span"); q.className = "cpg-tip-qty"; q.textContent = (it.qty != null ? it.qty : 0);
|
||||||
|
d1.appendChild(n); d1.appendChild(q);
|
||||||
|
html += d1.outerHTML;
|
||||||
|
});
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function move(e) {
|
||||||
|
// 커서 왼쪽에 표시
|
||||||
|
var w = tip.offsetWidth || 200;
|
||||||
|
var x = e.clientX - w - 14;
|
||||||
|
if (x < 6) x = e.clientX + 16; // 화면 왼쪽 벗어나면 오른쪽으로
|
||||||
|
var y = e.clientY + 12;
|
||||||
|
var maxY = window.innerHeight - tip.offsetHeight - 8;
|
||||||
|
if (y > maxY) y = maxY;
|
||||||
|
tip.style.left = x + "px";
|
||||||
|
tip.style.top = y + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll(".cpg-hover-item").forEach(function (el) {
|
||||||
|
el.addEventListener("mouseenter", function (e) {
|
||||||
|
var items = [];
|
||||||
|
try { items = JSON.parse(el.getAttribute("data-items") || "[]"); } catch (_) {}
|
||||||
|
tip.innerHTML = buildHtml(items);
|
||||||
|
tip.hidden = false;
|
||||||
|
move(e);
|
||||||
|
});
|
||||||
|
el.addEventListener("mousemove", move);
|
||||||
|
el.addEventListener("mouseleave", function () { tip.hidden = true; });
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{% extends "erp_base.html" %}
|
{% extends "erp_base.html" %}
|
||||||
|
|
||||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530l" />{% endblock %}
|
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530m" />{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<section class="cpg">
|
<section class="cpg">
|
||||||
|
|||||||
@@ -83,6 +83,20 @@
|
|||||||
.cpg-list-meta { font-size: 12px; margin-top: 4px; }
|
.cpg-list-meta { font-size: 12px; margin-top: 4px; }
|
||||||
.cpg-empty { padding: 16px 0; }
|
.cpg-empty { padding: 16px 0; }
|
||||||
|
|
||||||
|
/* 선택일 출고 hover 툴팁 (마우스 따라다님) */
|
||||||
|
.cpg-hover-tip {
|
||||||
|
position: fixed; z-index: 60; pointer-events: none;
|
||||||
|
background: var(--color-deep-black); color: #fff;
|
||||||
|
border-radius: 10px; padding: 8px 10px;
|
||||||
|
min-width: 160px; max-width: 280px;
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,.22);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.cpg-tip-row { display: flex; justify-content: space-between; gap: 12px; padding: 2px 0; }
|
||||||
|
.cpg-tip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
.cpg-tip-qty { font-weight: 600; flex: 0 0 auto; }
|
||||||
|
.cpg-tip-empty { color: #d4d4d4; }
|
||||||
|
|
||||||
/* ── 폼 ── */
|
/* ── 폼 ── */
|
||||||
.cpg-form-card { padding: 16px; margin-bottom: 16px; }
|
.cpg-form-card { padding: 16px; margin-bottom: 16px; }
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>{{ page_title or "ERP" }} — DBX Corporation</title>
|
<title>{{ page_title or "ERP" }} — DBX Corporation</title>
|
||||||
<link rel="stylesheet" href="/static/erp.css?v=20260530l" />
|
<link rel="stylesheet" href="/static/erp.css?v=20260530m" />
|
||||||
<link rel="stylesheet" href="/static/erp-shell.css?v=20260530l" />
|
<link rel="stylesheet" href="/static/erp-shell.css?v=20260530m" />
|
||||||
<link rel="stylesheet" href="/static/erp-attach-viewer.css" />
|
<link rel="stylesheet" href="/static/erp-attach-viewer.css" />
|
||||||
{% block head_extra %}{% endblock %}
|
{% block head_extra %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
Reference in New Issue
Block a user