d30dcbada4
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
140 lines
5.4 KiB
HTML
140 lines
5.4 KiB
HTML
{% extends "erp_base.html" %}
|
||
|
||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530p" />{% endblock %}
|
||
|
||
{% block content %}
|
||
<section class="cpg">
|
||
|
||
<!-- 페이지 액션 (달력 컬럼 폭에 맞춤: 신규 좌측 / 설정 달력 오른쪽 끝) -->
|
||
<div class="cpg-actions-grid">
|
||
<div class="cpg-actions-main">
|
||
<a class="erp-btn erp-btn-primary" href="/cupang/new">+ 신규 등록</a>
|
||
<span class="cpg-settings-btns">
|
||
<a class="erp-btn erp-btn-outline" href="/cupang/products">제품명 설정</a>
|
||
<a class="erp-btn erp-btn-outline" href="/cupang/centers">입고센터 관리</a>
|
||
<a class="erp-btn erp-btn-outline" href="/cupang/box-rules">박스 입수량 설정</a>
|
||
</span>
|
||
</div>
|
||
<div class="cpg-actions-spacer"></div>
|
||
</div>
|
||
|
||
<div class="cpg-layout">
|
||
<!-- ── 왼쪽: 큰 월간 달력 ── -->
|
||
<div class="erp-card cpg-cal-card">
|
||
<div class="cpg-cal-head">
|
||
<a class="erp-btn erp-btn-outline cpg-nav-btn"
|
||
href="/cupang/?year={{ prev_y }}&month={{ prev_m }}">‹</a>
|
||
<h2 class="cpg-cal-title">{{ year }}년 {{ month }}월</h2>
|
||
<a class="erp-btn erp-btn-outline cpg-nav-btn"
|
||
href="/cupang/?year={{ next_y }}&month={{ next_m }}">›</a>
|
||
</div>
|
||
|
||
<div class="cpg-cal-grid">
|
||
{% for wd in weekdays %}
|
||
<div class="cpg-cal-wd {% if loop.index0 == 0 %}cpg-sun{% elif loop.index0 == 6 %}cpg-sat{% endif %}">{{ wd }}</div>
|
||
{% endfor %}
|
||
|
||
{% for week in cal_weeks %}
|
||
{% for cell in week %}
|
||
<a class="cpg-cal-cell
|
||
{% if not cell.in_month %}cpg-out{% endif %}
|
||
{% if cell.is_today %}cpg-today{% endif %}
|
||
{% if cell.is_selected %}cpg-selected{% endif %}
|
||
{% if cell.is_sunday or cell.is_holiday %}cpg-red{% elif cell.is_saturday %}cpg-blue{% endif %}"
|
||
href="/cupang/?year={{ year }}&month={{ month }}&date={{ cell.date }}">
|
||
<span class="cpg-cal-day">{{ cell.day }}</span>
|
||
<span class="cpg-cal-badges">
|
||
{% if cell.counts.document %}<span class="erp-badge erp-badge-neutral cpg-mini">작성 {{ cell.counts.document }}</span>{% endif %}
|
||
{% if cell.counts.ship %}<span class="erp-badge erp-badge-inverse cpg-mini">출고 {{ cell.counts.ship }}</span>{% endif %}
|
||
{% if cell.counts.arrival %}<span class="erp-badge erp-badge-success cpg-mini">입고 {{ cell.counts.arrival }}</span>{% endif %}
|
||
</span>
|
||
</a>
|
||
{% endfor %}
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── 오른쪽: 선택일 출고 묶음 리스트 ── -->
|
||
<div class="erp-card cpg-list-card">
|
||
<div class="cpg-list-head">
|
||
<h2>{{ selected_date }} 출고</h2>
|
||
<span class="erp-muted">{{ sel_shipments|length }}건</span>
|
||
</div>
|
||
|
||
{% if sel_shipments %}
|
||
<ul class="cpg-list">
|
||
{% for s in sel_shipments %}
|
||
<li class="cpg-list-item">
|
||
<a href="/cupang/{{ s.id }}" class="cpg-list-link cpg-hover-item"
|
||
data-items='{{ s.tip_items | tojson }}'>
|
||
<div class="cpg-list-top">
|
||
<strong>{{ s.center_name_snapshot or '센터 미지정' }}</strong>
|
||
</div>
|
||
<div class="cpg-list-meta erp-muted">
|
||
출고 {{ s.ship_date }} · 입고 {{ s.center_arrival_date }} · {{ s.ship_method }}
|
||
{% if s.outbound_summary %}<br>{{ s.outbound_summary }}{% endif %}
|
||
</div>
|
||
</a>
|
||
</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p class="erp-muted cpg-empty">선택한 날짜의 출고 묶음이 없습니다.
|
||
<a href="/cupang/new">신규 등록</a></p>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- hover 툴팁 (마우스 따라다님, 커서 왼쪽) -->
|
||
<div id="cpg-hover-tip" class="cpg-hover-tip" hidden></div>
|
||
|
||
</section>
|
||
{% 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 %}
|