Files
dbx-main/app/modules/cupang/templates/cupang/centers.html
T
king 99c0581d9a fix(cupang): 상자 계산 화면이 내용만큼 늘고 페이지가 스크롤되게
.cpg 가 flex:1 1 auto + min-height:0 이라 남은 높이에 맞춰 눌리기만 해서
③ 이 늘어나도 페이지 높이가 그대로였다(=스크롤 안 됨).
이 화면에만 .cpg-page-grow 를 붙여 flex:0 0 auto 로 두고,
페이지 스크롤 시 ①② 내부 스크롤 높이를 다시 계산한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 17:33:09 +09:00

188 lines
7.5 KiB
HTML

{% extends "erp_base.html" %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901w" />{% endblock %}
{% block content %}
<section class="cpg">
<div class="erp-page-actions">
<a class="erp-btn erp-btn-primary" href="/cupang/">◀◀ 달력</a>
</div>
<div class="erp-card cpg-form-card cpg-center-card">
<!-- 상단: 추가 + 검색 -->
<div class="cpg-center-bar">
<form method="post" action="/cupang/centers" class="cpg-center-addform">
<input class="erp-input cpg-center-addinput" type="text" name="name"
placeholder="센터명 입력 (예: 대구3)" required autocomplete="off" />
<button type="submit" class="erp-btn erp-btn-primary">추가</button>
</form>
<input class="erp-input cpg-center-search" type="search" id="cpgCenterSearch"
placeholder="센터 검색" autocomplete="off" />
</div>
<div class="cpg-card-head cpg-center-head">
<h2>센터 목록 <span class="erp-muted" id="cpgCenterCount">({{ centers|length }})</span></h2>
<span class="erp-muted">지역별로 묶어 표시. 이름 변경은 지원하지 않음 — 삭제 후 새로 등록.</span>
</div>
<!-- 목록: 지역 그룹 패널, 위→아래로 읽고 열로 흐름 -->
<div class="cpg-center-cols" id="cpgCenterGrid">
{% for g in center_groups %}
<section class="cpg-center-group" data-group="{{ g.name|lower }}">
<button type="button" class="cpg-center-gtitle" aria-expanded="true">
<span class="cpg-center-caret" aria-hidden="true"></span>
<span class="cpg-center-gname">{{ g.name }}</span>
<span class="cpg-center-gcount">{{ g.count }}</span>
</button>
<div class="cpg-center-glist">
{% for c in g["items"] %}
<div class="cpg-center-row {% if not c.active %}is-inactive{% endif %}" data-name="{{ c.name|lower }}">
<span class="cpg-center-dot" title="{% if c.active %}활성{% else %}비활성{% endif %}"></span>
<span class="cpg-center-name">{{ c.name }}</span>
<span class="cpg-center-acts">
<form method="post" action="/cupang/centers/{{ c.id }}/edit" class="cpg-inline-form">
<input type="hidden" name="active" value="{% if c.active %}0{% else %}1{% endif %}" />
<button type="submit" class="cpg-icon-btn"
title="{% if c.active %}비활성으로 전환{% else %}활성으로 전환{% endif %}">{% if c.active %}비활성{% else %}활성{% endif %}</button>
</form>
<button type="button" class="cpg-icon-btn is-danger" title="삭제"
data-del-url="/cupang/centers/{{ c.id }}/delete" data-del-name="{{ c.name }}">삭제</button>
</span>
</div>
{% endfor %}
</div>
</section>
{% endfor %}
</div>
<p class="cpg-center-empty erp-muted" id="cpgCenterEmpty" hidden>검색 결과 없음</p>
</div>
</section>
<!-- 화면 가운데 알림/확인 팝업 -->
<div class="cpg-modal" id="cpgCenterDlg" hidden>
<div class="cpg-modal-back" data-dlg-close></div>
<div class="cpg-modal-box cpg-center-dlg" role="dialog" aria-modal="true" aria-labelledby="cpgCenterDlgTitle">
<h3 id="cpgCenterDlgTitle">알림</h3>
<p class="cpg-center-dlgmsg" id="cpgCenterDlgMsg"></p>
<div class="cpg-dlg-actions cpg-center-dlgact">
<button type="button" class="erp-btn erp-btn-outline" id="cpgCenterDlgCancel" data-dlg-close hidden>취소</button>
<button type="button" class="erp-btn erp-btn-primary" id="cpgCenterDlgOk">확인</button>
</div>
</div>
</div>
<form method="post" id="cpgCenterDelForm" hidden></form>
<script>
(function () {
// ── 가운데 팝업 (alert/confirm 대체) ──
var dlg = document.getElementById('cpgCenterDlg');
var dlgTitle = document.getElementById('cpgCenterDlgTitle');
var dlgMsg = document.getElementById('cpgCenterDlgMsg');
var dlgOk = document.getElementById('cpgCenterDlgOk');
var dlgCancel = document.getElementById('cpgCenterDlgCancel');
var onConfirm = null;
var lastFocus = null;
function closeDlg() {
dlg.hidden = true;
onConfirm = null;
if (lastFocus && lastFocus.focus) lastFocus.focus();
}
function openDlg(opts) {
lastFocus = document.activeElement;
dlgTitle.textContent = opts.title || '알림';
dlgMsg.textContent = opts.message || '';
onConfirm = opts.onConfirm || null;
dlgCancel.hidden = !opts.onConfirm;
dlgOk.textContent = opts.okText || '확인';
dlgOk.classList.toggle('erp-btn-danger', !!opts.danger);
dlgOk.classList.toggle('erp-btn-primary', !opts.danger);
dlg.hidden = false;
dlgOk.focus();
}
dlgOk.addEventListener('click', function () {
var fn = onConfirm;
closeDlg();
if (fn) fn();
});
Array.prototype.forEach.call(dlg.querySelectorAll('[data-dlg-close]'), function (el) {
el.addEventListener('click', closeDlg);
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && !dlg.hidden) closeDlg();
});
// ── 추가 결과 알림 (중복 등록 차단) ──
var flash = {{ flash|tojson }};
var fname = {{ flash_name|tojson }};
if (flash === 'dup') {
openDlg({ title: '이미 등록된 센터', message: '"' + fname + '" 센터는 이미 목록에 있습니다.' });
} else if (flash === 'dup_inactive') {
openDlg({
title: '이미 등록된 센터',
message: '"' + fname + '" 센터는 이미 목록에 있습니다. 지금은 비활성 상태이니 목록에서 [활성] 을 눌러 사용하세요.'
});
}
if (flash) history.replaceState(null, '', '/cupang/centers');
// ── 삭제 확인 ──
var delForm = document.getElementById('cpgCenterDelForm');
document.addEventListener('click', function (e) {
var btn = e.target.closest('[data-del-url]');
if (!btn) return;
openDlg({
title: '센터 삭제',
message: '"' + btn.dataset.delName + '" 센터를 삭제할까요?',
okText: '삭제',
danger: true,
onConfirm: function () {
delForm.action = btn.dataset.delUrl;
delForm.submit();
}
});
});
// ── 그룹 접기 ──
document.addEventListener('click', function (e) {
var head = e.target.closest('.cpg-center-gtitle');
if (!head) return;
var group = head.closest('.cpg-center-group');
var collapsed = group.classList.toggle('is-collapsed');
head.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
});
// ── 검색 ──
var box = document.getElementById('cpgCenterSearch');
var grid = document.getElementById('cpgCenterGrid');
var count = document.getElementById('cpgCenterCount');
var empty = document.getElementById('cpgCenterEmpty');
if (!box || !grid) return;
var groups = Array.prototype.slice.call(grid.querySelectorAll('.cpg-center-group'));
box.addEventListener('input', function () {
var q = box.value.trim().toLowerCase();
var n = 0;
groups.forEach(function (g) {
var shown = 0;
Array.prototype.forEach.call(g.querySelectorAll('.cpg-center-row'), function (r) {
var hit = !q || (r.dataset.name || '').indexOf(q) !== -1;
r.style.display = hit ? '' : 'none';
if (hit) shown += 1;
});
g.style.display = shown ? '' : 'none';
if (q && shown) g.classList.remove('is-collapsed');
n += shown;
});
if (count) count.textContent = '(' + n + ')';
if (empty) empty.hidden = n !== 0;
});
})();
</script>
{% endblock %}