feat(mgmt-perf): 업로드 영역 하단 배치, 업로드 삭제 API, 앱 내 밝은 배경
- 대시보드 조회를 위·엑셀 업로드를 아래로 재배치 - DELETE /api/mgmt-perf/upload/:id 및 최근 업로드 행 삭제 버튼 - dashboard.css 전역 body 어두운 배경을 body.mgmt-perf-standalone로 한정, 임베드는 투명 - mgmt_perf_embed에 standalone 클래스 유지 Made-with: Cursor
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
border: 1px solid var(--border, #e0e0e0);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
background: var(--panel-bg, #fafafa);
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
.mgmt-upload-panel h2 {
|
||||
font-size: 1.05rem;
|
||||
@@ -86,6 +87,11 @@
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
min-height: 400px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
.mgmt-perf-page .mgmt-perf-embed .container {
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
.mgmt-upload-history {
|
||||
margin-top: 16px;
|
||||
@@ -100,11 +106,35 @@
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #eee;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.mgmt-upload-history th:last-child,
|
||||
.mgmt-upload-history td.mgmt-upload-delete-cell {
|
||||
text-align: right;
|
||||
width: 88px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.mgmt-upload-history th {
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
}
|
||||
.btn-mgmt-upload-delete {
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #fecaca;
|
||||
background: #fff;
|
||||
color: #b91c1c;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
}
|
||||
.btn-mgmt-upload-delete:hover {
|
||||
background: #fef2f2;
|
||||
}
|
||||
.btn-mgmt-upload-delete:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -123,10 +153,25 @@
|
||||
</p>
|
||||
|
||||
<div class="mgmt-perf-split">
|
||||
<section class="mgmt-dash-panel" aria-labelledby="mgmt-dash-heading">
|
||||
<h2 id="mgmt-dash-heading">대시보드 조회</h2>
|
||||
<div class="mgmt-dash-inline-wrap">
|
||||
<div class="mgmt-perf-embed" id="mgmtPerfDashRoot">
|
||||
<%- include('partials/mgmt_perf_dashboard_container', {
|
||||
dashboardTitle: typeof dashboardTitle !== 'undefined' ? dashboardTitle : '경영성과 대시보드',
|
||||
quarterLabel: typeof quarterLabel !== 'undefined' ? quarterLabel : 'Q1',
|
||||
}) %>
|
||||
</div>
|
||||
</div>
|
||||
<script type="application/json" id="mgmt-perf-payload-json"><%- typeof payloadJson !== 'undefined' ? payloadJson : '{}' %></script>
|
||||
<script src="/mgmt-perf/chart.umd.min.js"></script>
|
||||
<script src="/mgmt-perf/dashboard-app.js"></script>
|
||||
</section>
|
||||
|
||||
<section class="mgmt-upload-panel" aria-labelledby="mgmt-upload-heading">
|
||||
<h2 id="mgmt-upload-heading">엑셀 업로드</h2>
|
||||
<p class="subtitle" style="margin: 0 0 12px; font-size: 14px">
|
||||
매출 집계 엑셀(<strong>매출일보</strong> 시트 포함)을 업로드하면 스냅샷이 저장되고, 아래 대시보드에 반영됩니다.
|
||||
매출 집계 엑셀(<strong>매출일보</strong> 시트 포함)을 업로드하면 스냅샷이 저장되고, <strong>위</strong> 대시보드에 반영됩니다.
|
||||
</p>
|
||||
<form id="mgmtPerfUploadForm" class="mgmt-upload-form" enctype="multipart/form-data">
|
||||
<label>
|
||||
@@ -152,7 +197,7 @@
|
||||
</form>
|
||||
<div id="mgmtPerfUploadMsg" class="mgmt-upload-msg" role="status"></div>
|
||||
<% if (typeof uploadHistory !== 'undefined' && uploadHistory && uploadHistory.length) { %>
|
||||
<div class="mgmt-upload-history">
|
||||
<div class="mgmt-upload-history" id="mgmtUploadHistory">
|
||||
<strong>최근 업로드</strong>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -160,6 +205,7 @@
|
||||
<th>일시</th>
|
||||
<th>파일명</th>
|
||||
<th>연도·분기</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -168,6 +214,9 @@
|
||||
<td><%= u.created_at ? new Date(u.created_at).toLocaleString('ko-KR') : '-' %></td>
|
||||
<td><%= u.original_filename || '-' %></td>
|
||||
<td><%= u.fiscal_year != null && u.fiscal_year !== '' ? u.fiscal_year + '년 Q' + u.quarter : '-' %></td>
|
||||
<td class="mgmt-upload-delete-cell">
|
||||
<button type="button" class="btn-mgmt-upload-delete" data-upload-id="<%= u.id != null ? String(u.id) : '' %>">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
@@ -175,21 +224,6 @@
|
||||
</div>
|
||||
<% } %>
|
||||
</section>
|
||||
|
||||
<section class="mgmt-dash-panel" aria-labelledby="mgmt-dash-heading">
|
||||
<h2 id="mgmt-dash-heading">대시보드 조회</h2>
|
||||
<div class="mgmt-dash-inline-wrap">
|
||||
<div class="mgmt-perf-embed" id="mgmtPerfDashRoot">
|
||||
<%- include('partials/mgmt_perf_dashboard_container', {
|
||||
dashboardTitle: typeof dashboardTitle !== 'undefined' ? dashboardTitle : '경영성과 대시보드',
|
||||
quarterLabel: typeof quarterLabel !== 'undefined' ? quarterLabel : 'Q1',
|
||||
}) %>
|
||||
</div>
|
||||
</div>
|
||||
<script type="application/json" id="mgmt-perf-payload-json"><%- typeof payloadJson !== 'undefined' ? payloadJson : '{}' %></script>
|
||||
<script src="/mgmt-perf/chart.umd.min.js"></script>
|
||||
<script src="/mgmt-perf/dashboard-app.js"></script>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
@@ -247,6 +281,53 @@
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var root = document.getElementById("mgmtUploadHistory");
|
||||
if (!root) return;
|
||||
root.addEventListener("click", function (e) {
|
||||
var t = e.target;
|
||||
if (!t || !t.closest) return;
|
||||
var del = t.closest(".btn-mgmt-upload-delete");
|
||||
if (!del) return;
|
||||
var id = del.getAttribute("data-upload-id");
|
||||
if (!id) return;
|
||||
if (!window.confirm("이 업로드 기록을 삭제할까요?")) return;
|
||||
del.disabled = true;
|
||||
fetch("/api/mgmt-perf/upload/" + encodeURIComponent(id), {
|
||||
method: "DELETE",
|
||||
credentials: "same-origin",
|
||||
})
|
||||
.then(function (r) {
|
||||
return r.text().then(function (text) {
|
||||
var j = {};
|
||||
if (text) {
|
||||
try {
|
||||
j = JSON.parse(text);
|
||||
} catch (parseErr) {
|
||||
j = { error: text.slice(0, 200) };
|
||||
}
|
||||
}
|
||||
return { ok: r.ok, body: j, status: r.status };
|
||||
});
|
||||
})
|
||||
.then(function (ref) {
|
||||
if (ref.ok && ref.body && ref.body.ok === true) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
var err =
|
||||
(ref.body && (ref.body.error || ref.body.message)) || "삭제에 실패했습니다.";
|
||||
window.alert(err);
|
||||
})
|
||||
.catch(function () {
|
||||
window.alert("삭제 요청에 실패했습니다.");
|
||||
})
|
||||
.finally(function () {
|
||||
del.disabled = false;
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user