feat: unify 8081 dashboard design system and views

This commit is contained in:
hyunho
2026-04-01 14:02:05 +09:00
parent 637b390024
commit fb5b0f00c2
27 changed files with 12596 additions and 818 deletions

View File

@@ -15,6 +15,8 @@ const organizationHistoryControls = document.getElementById("organization-histor
const organizationMonthSelect = document.getElementById("organization-month-select");
const organizationCompareBtn = document.getElementById("organization-compare-btn");
const navButtons = Array.from(document.querySelectorAll(".header-center [data-view]"));
const ledgerFrame = document.getElementById("ledger-frame");
const ledgerStage = document.getElementById("ledger-stage");
const organizationFrame = document.getElementById("organization-frame");
const organizationStage = document.getElementById("organization-stage");
const projectFrame = document.getElementById("project-frame");
@@ -151,7 +153,7 @@ const seatMapState = {
forceReadOnly: false,
};
let currentView = "project";
let currentView = "ledger";
const globalDateState = {
loaded: false,
startDate: "",
@@ -364,6 +366,10 @@ function buildSeatMapAsOfQuery() {
}
function notifyEmbeddedTabActivated() {
if (currentView === "ledger" && ledgerFrame?.contentWindow) {
ledgerFrame.contentWindow.postMessage({ source: "total-control", type: "embedded-host" }, window.location.origin);
ledgerFrame.contentWindow.postMessage({ source: "total-control", type: "tab-activated", tab: "business" }, window.location.origin);
}
if (currentView === "project" && projectFrame?.contentWindow) {
projectFrame.contentWindow.postMessage({ source: "total-control", type: "tab-activated", tab: "project" }, window.location.origin);
}
@@ -372,6 +378,49 @@ function notifyEmbeddedTabActivated() {
}
}
let ledgerDefaultSourcePromise = null;
async function fetchDefaultLedgerSource() {
if (!ledgerDefaultSourcePromise) {
ledgerDefaultSourcePromise = fetch("/api/integration/business-ledger-default")
.then(async (response) => {
if (!response.ok) {
throw new Error("기본 사업관리대장 원본을 불러오지 못했습니다.");
}
const fileName = response.headers.get("x-source-filename") || "사업관리대장-1.xlsx";
const buffer = await response.arrayBuffer();
if (!buffer || !buffer.byteLength) {
throw new Error("기본 사업관리대장 원본 데이터가 비어 있습니다.");
}
return { fileName, buffer };
})
.catch((error) => {
ledgerDefaultSourcePromise = null;
throw error;
});
}
return ledgerDefaultSourcePromise;
}
async function pushDefaultLedgerSourceToFrame(force = false) {
if (!ledgerFrame?.contentWindow) return;
if (ledgerFrame.dataset.defaultLedgerLoaded === "true" && !force) return;
try {
const { fileName, buffer } = await fetchDefaultLedgerSource();
ledgerFrame.contentWindow.postMessage(
{ source: "total-control", type: "embedded-host" },
window.location.origin,
);
ledgerFrame.contentWindow.postMessage(
{ source: "total-upload", type: "business", fileName, buffer },
window.location.origin,
);
ledgerFrame.dataset.defaultLedgerLoaded = "true";
} catch (error) {
console.error("사업관리대장 기본 원본 전달에 실패했습니다.", error);
}
}
async function ensureGlobalDateRangeLoaded() {
if (globalDateState.loaded) return;
try {
@@ -1571,10 +1620,15 @@ function setActiveView(view) {
});
const isOrganization = currentView === "organization";
const isLedger = currentView === "ledger";
const isProject = currentView === "project";
const isTeam = currentView === "team";
const isSeatMapAdmin = currentView === "seatmap-admin";
const isSeatMapReadonly = currentView === "seatmap-readonly";
if (ledgerStage) {
ledgerStage.hidden = !isLedger;
ledgerStage.style.display = isLedger ? "flex" : "none";
}
if (organizationStage) {
organizationStage.hidden = !isOrganization;
organizationStage.style.display = isOrganization ? "flex" : "none";
@@ -1596,11 +1650,15 @@ function setActiveView(view) {
seatMapReadonlyStage.style.display = isSeatMapReadonly ? "flex" : "none";
}
if (emptyStage) {
const showEmpty = !isOrganization && !isProject && !isTeam && !isSeatMapAdmin && !isSeatMapReadonly;
const showEmpty = !isLedger && !isOrganization && !isProject && !isTeam && !isSeatMapAdmin && !isSeatMapReadonly;
emptyStage.hidden = !showEmpty;
emptyStage.style.display = showEmpty ? "flex" : "none";
}
if (isLedger && previousView !== "ledger" && ledgerFrame) {
const frameSrc = ledgerFrame.dataset.src || ledgerFrame.src;
ledgerFrame.src = resolveAppUrl(frameSrc);
}
if (isOrganization && previousView !== "organization" && organizationFrame) {
const frameSrc = organizationFrame.dataset.src || organizationFrame.src;
organizationFrame.src = resolveAppUrl(frameSrc);
@@ -1671,7 +1729,7 @@ if (loginForm) {
body: formData,
});
setSession(payload);
setActiveView("project");
setActiveView("ledger");
loginForm.reset();
loginMessage.textContent = "";
renderAuth();
@@ -1728,6 +1786,13 @@ organizationFrame?.addEventListener("load", () => {
postOrganizationHistoryState();
});
ledgerFrame?.addEventListener("load", () => {
if (currentView === "ledger") {
notifyEmbeddedTabActivated();
}
void pushDefaultLedgerSourceToFrame(true);
});
projectFrame?.addEventListener("load", () => {
postGlobalDateRangeToFrame(projectFrame);
if (currentView === "project") {

View File

@@ -0,0 +1,730 @@
@import url("/design-tokens.css?v=20260401-01");
:root {
--ds-hero-text: #f7f0e4;
--ds-hero-border: rgba(242, 196, 132, 0.22);
--ds-hero-surface: rgba(255, 255, 255, 0.08);
--ds-hero-surface-strong: rgba(255, 255, 255, 0.1);
--ds-hero-text-muted: rgba(255, 244, 230, 0.72);
--ds-hero-text-soft: rgba(255, 244, 230, 0.56);
--ds-hero-line: rgba(242, 196, 132, 0.18);
--ds-danger-soft: rgba(169, 72, 50, 0.1);
--ds-danger-line: rgba(169, 72, 50, 0.22);
--ds-success-soft: rgba(47, 153, 115, 0.14);
--ds-success-line: rgba(47, 153, 115, 0.24);
--ds-brand-soft-surface: rgba(15, 58, 47, 0.1);
--ds-brand-soft-line: rgba(15, 58, 47, 0.18);
--ds-accent-soft-surface: rgba(242, 196, 132, 0.18);
--ds-accent-soft-line: rgba(214, 138, 58, 0.24);
}
.ds-panel,
.payment-panel {
background: rgba(255, 250, 243, 0.96);
border: 1px solid var(--ds-line-soft);
box-shadow: var(--ds-shadow-soft);
}
.ds-panel-head,
.payment-panel-head {
background: rgba(255, 250, 243, 0.92);
border-bottom: 1px solid var(--ds-line-soft);
}
.ds-kpi-card,
.payment-kpi-card {
border: 1px solid var(--ds-line-soft);
background: linear-gradient(180deg, rgba(255, 250, 243, 0.96) 0%, rgba(248, 242, 232, 0.96) 100%);
box-shadow: var(--ds-shadow-soft);
color: var(--ds-ink);
}
.ds-kpi-inverse,
.payment-kpi-inverse {
color: #fffaf3;
}
.ds-kpi-people,
.payment-kpi-people {
background: linear-gradient(135deg, var(--ds-brand) 0%, var(--ds-brand-soft) 100%);
border-color: rgba(15, 58, 47, 0.2);
}
.ds-subhead,
.payment-subhead {
color: var(--ds-text-muted);
}
.ds-empty,
.payment-empty {
color: #9b937f;
}
.ds-tooltip,
.payment-tooltip {
background: var(--ds-brand-deep);
color: #fffaf3;
}
.ds-filter-surface,
.payment-filter-bar {
background: rgba(246, 237, 221, 0.8);
border: 1px solid var(--ds-line);
}
.ds-filter-toggle,
.payment-filter-toggle {
background: var(--ds-brand);
border-color: rgba(15, 58, 47, 0.28);
color: #fffaf3;
}
.ds-reset-button,
.payment-reset-btn {
background: rgba(255, 250, 243, 0.96);
border: 1px solid var(--ds-line);
color: var(--ds-text-muted);
}
.ds-reset-button:hover,
.payment-reset-btn:hover {
color: var(--ds-brand-soft);
background: rgba(255, 255, 255, 0.98);
}
.ds-table-head,
.payment-table-head {
background: rgba(246, 237, 221, 0.82);
}
.ds-table-head-row,
.payment-table-head-row {
color: var(--ds-brand-deep);
border-bottom: 1px solid var(--ds-line);
}
.ds-table-row,
.payment-data-row {
border-color: #f0e5d2;
}
.ds-table-row:hover,
.payment-data-row:hover {
background: #f6eddd;
}
.ds-axis-cell,
.payment-axis-cell {
border-right: 1px solid var(--ds-line-soft);
}
.ds-axis-cell-idle,
.payment-axis-cell-idle {
background: rgba(255, 250, 243, 0.96);
color: var(--ds-ink);
}
.ds-axis-cell-idle:hover,
.payment-axis-cell-idle:hover {
background: rgba(234, 220, 196, 0.52);
color: var(--ds-brand-deep);
}
.ds-axis-cell-active,
.payment-axis-cell-active {
background: rgba(234, 220, 196, 0.78);
color: var(--ds-brand-deep);
}
.ds-project-cell,
.payment-project-cell {
color: var(--ds-brand-deep);
font-weight: 800;
}
.ds-project-cell:hover,
.payment-project-cell:hover {
background: #efe2ca;
color: #214634;
}
.ds-income,
.payment-income {
color: var(--ds-status-success);
}
.ds-expense,
.payment-expense {
color: var(--ds-status-danger);
}
.ds-progress-track,
.payment-progress-track {
background: rgba(217, 197, 168, 0.45);
}
.ds-progress-track-grand,
.payment-progress-track-grand {
background: rgba(75, 135, 179, 0.24);
}
.ds-progress-track-mid,
.payment-progress-track-mid {
background: rgba(214, 138, 58, 0.22);
}
.ds-mode-chip,
.payment-mode-chip {
color: var(--ds-brand-soft);
background: rgba(242, 196, 132, 0.22);
border: 1px solid rgba(214, 138, 58, 0.28);
}
.ds-name-chip,
.payment-name-chip {
background: rgba(246, 237, 221, 0.76);
border: 1px solid var(--ds-line-soft);
color: var(--ds-text-soft);
}
.ds-divider-top,
.payment-divider-top {
border-top: 1px solid var(--ds-line-soft);
}
.ds-divider-left,
.payment-divider-left {
border-left: 1px solid var(--ds-line-soft);
}
.ds-divider-mark,
.payment-divider-mark {
color: rgba(183, 170, 147, 0.92);
}
.ds-mini-table-shell,
.payment-mini-table-shell {
border: 1px solid var(--ds-line-soft);
}
.ds-mini-table-head,
.payment-mini-table-head {
background: rgba(246, 237, 221, 0.68);
color: var(--ds-text-muted);
}
.ds-mini-table-row,
.payment-mini-table-row {
border-top: 1px solid rgba(217, 197, 168, 0.36);
color: var(--ds-text-soft);
}
.ds-group-title,
.payment-group-title {
background: var(--ds-brand);
color: #fffaf3;
}
.ds-strong,
.payment-strong {
color: var(--ds-ink);
}
.ds-muted,
.payment-muted {
color: var(--ds-text-soft);
}
.ds-accent-text,
.payment-icon-accent {
color: var(--ds-brand-soft);
}
.ds-position-chip,
.position-chip {
background: rgba(246, 237, 221, 0.76);
}
.ds-position-text,
.position-text {
color: var(--ds-text-soft);
}
.ds-position-border,
.position-border {
border-color: rgba(217, 197, 168, 0.46);
}
.ds-position-dot,
.position-dot {
box-shadow: 0 0 0 2px rgba(255, 250, 243, 0.9);
}
.position-executive.position-chip { background: rgba(15, 58, 47, 0.1); }
.position-executive.position-text { color: var(--ds-brand); }
.position-executive.position-border { border-color: rgba(15, 58, 47, 0.22); }
.position-executive.position-dot { background: var(--ds-brand); }
.position-principal.position-chip { background: rgba(26, 86, 69, 0.1); }
.position-principal.position-text { color: var(--ds-brand-soft); }
.position-principal.position-border { border-color: rgba(26, 86, 69, 0.22); }
.position-principal.position-dot { background: var(--ds-brand-soft); }
.position-senior.position-chip { background: rgba(47, 153, 115, 0.12); }
.position-senior.position-text { color: var(--ds-mint); }
.position-senior.position-border { border-color: rgba(47, 153, 115, 0.26); }
.position-senior.position-dot { background: var(--ds-mint); }
.position-associate.position-chip { background: rgba(75, 135, 179, 0.12); }
.position-associate.position-text { color: var(--ds-info); }
.position-associate.position-border { border-color: rgba(75, 135, 179, 0.22); }
.position-associate.position-dot { background: var(--ds-info); }
.position-staff.position-chip { background: rgba(214, 138, 58, 0.12); }
.position-staff.position-text { color: var(--ds-status-warning); }
.position-staff.position-border { border-color: rgba(214, 138, 58, 0.24); }
.position-staff.position-dot { background: var(--ds-status-warning); }
.position-member.position-chip { background: rgba(102, 117, 109, 0.12); }
.position-member.position-text { color: var(--ds-text-soft); }
.position-member.position-border { border-color: rgba(102, 117, 109, 0.24); }
.position-member.position-dot { background: var(--ds-text-soft); }
.position-unset.position-chip { background: rgba(183, 170, 147, 0.18); }
.position-unset.position-text { color: #8b7e69; }
.position-unset.position-border { border-color: rgba(183, 170, 147, 0.3); }
.position-unset.position-dot { background: #b7aa93; }
.popup-wrap {
max-width: 1680px;
margin: 0 auto;
padding: 20px;
}
.popup-head {
margin-bottom: 14px;
padding: 18px 20px;
border: 1px solid rgba(217, 197, 168, 0.62);
border-radius: 24px;
background: linear-gradient(180deg, #fff8ee 0%, #f4e9d7 100%);
box-shadow: 0 18px 36px rgba(15, 58, 47, 0.08);
}
.popup-title {
font-size: 28px;
font-weight: 900;
line-height: 1.2;
color: var(--ds-ink);
}
.popup-sub {
margin-top: 6px;
font-size: 13px;
font-weight: 800;
color: var(--ds-text-muted);
}
.inline-panel {
padding: 0;
display: grid;
gap: 14px;
}
.project-head-grid {
display: grid;
grid-template-columns: minmax(0, 1.95fr) minmax(280px, 0.72fr);
gap: 10px;
align-items: start;
}
.project-head-main {
display: flex;
flex-direction: column;
gap: 10px;
min-width: 0;
}
.project-contact-stack {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
width: 100%;
}
.inline-card,
.ledger-block,
.popup-wrap .ledger-block.collect {
background: rgba(255, 250, 243, 0.98) !important;
border: 1px solid rgba(217, 197, 168, 0.56) !important;
border-radius: 24px !important;
box-shadow: 0 16px 32px rgba(15, 58, 47, 0.08) !important;
}
.inline-card {
padding: 16px 18px;
}
.project-meta-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px 12px;
}
.kv {
padding: 12px 14px;
border-radius: 18px;
background: linear-gradient(180deg, #fffdf8 0%, #f4e9d7 100%);
border: 1px solid rgba(217, 197, 168, 0.46);
}
.kvk,
.summary-label {
font-size: 11px;
font-weight: 900;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #8a6b3d;
}
.kvv {
font-size: 15px;
font-weight: 900;
color: var(--ds-ink);
line-height: 1.35;
word-break: keep-all;
}
.summary-note {
margin-top: 6px;
font-size: 12px;
font-weight: 800;
color: var(--ds-text-muted);
line-height: 1.45;
}
.summary-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
}
.summary-card {
padding: 14px 16px;
border-radius: 18px;
background: linear-gradient(180deg, #fffdf8 0%, #f4e9d7 100%);
border: 1px solid rgba(217, 197, 168, 0.46);
box-shadow: none;
}
.summary-card.receivable {
background: linear-gradient(180deg, var(--ds-danger-soft) 0%, rgba(255, 248, 238, 0.98) 100%);
border-color: var(--ds-danger-line);
}
.summary-value {
margin-top: 8px;
font-size: 24px;
font-weight: 900;
color: var(--ds-ink);
line-height: 1.15;
}
.summary-card.receivable .summary-value {
color: var(--ds-status-danger);
}
.project-progress {
margin-top: 10px;
height: 12px;
border-radius: var(--ds-radius-pill);
overflow: hidden;
background: rgba(217, 197, 168, 0.48);
box-shadow: inset 0 1px 2px rgba(15, 58, 47, 0.08);
}
.progress .bar {
height: 100%;
border-radius: var(--ds-radius-pill);
background: linear-gradient(90deg, var(--ds-brand-soft) 0%, var(--ds-mint) 100%);
box-shadow: 0 8px 18px rgba(47, 153, 115, 0.18);
}
.ledger-stack {
display: grid;
gap: 12px;
}
.ledger-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
padding: 18px 18px 14px;
border-bottom: 1px solid rgba(217, 197, 168, 0.38) !important;
background: linear-gradient(180deg, #fffdf8 0%, #f4e9d7 100%) !important;
}
.ledger-head-left {
display: flex;
align-items: flex-start;
gap: 12px;
min-width: 0;
}
.ledger-icon {
width: 36px;
height: 36px;
border-radius: 12px;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #fff8ee 0%, #f2dec0 100%) !important;
color: var(--ds-accent-strong) !important;
font-weight: 900;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.65);
}
.ledger-name {
font-size: 16px;
font-weight: 900;
color: var(--ds-ink) !important;
line-height: 1.2;
}
.ledger-sub {
margin-top: 4px;
font-size: 12px;
font-weight: 800;
color: var(--ds-text-muted) !important;
line-height: 1.45;
}
.ledger-pill {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 12px;
border-radius: var(--ds-radius-pill);
background: var(--ds-brand-soft-surface) !important;
border: 1px solid var(--ds-brand-soft-line) !important;
color: var(--ds-brand-soft) !important;
font-size: 12px;
font-weight: 900;
white-space: nowrap;
}
.ledger-table-wrap {
padding: 0 16px 16px;
background: transparent !important;
}
.ledger-table {
width: 100%;
border-collapse: collapse;
background: transparent !important;
}
.ledger-table thead th {
padding: 12px 10px;
background: var(--ds-brand) !important;
color: #fff5e6 !important;
font-size: 12px;
font-weight: 900;
text-align: left;
border-right: 1px solid rgba(242, 196, 132, 0.18) !important;
}
.ledger-table thead th:last-child {
border-right: 0;
}
.ledger-table tbody td {
padding: 12px 10px;
border-bottom: 1px solid rgba(217, 197, 168, 0.34) !important;
vertical-align: top;
font-size: 13px;
font-weight: 800;
color: var(--ds-ink) !important;
background: rgba(255, 250, 243, 0.72) !important;
}
.ledger-table tbody tr:last-child td {
border-bottom: 0;
}
.ledger-main {
display: block;
color: var(--ds-ink) !important;
font-weight: 900;
}
.ledger-muted,
.ledger-note {
display: block;
margin-top: 4px;
color: var(--ds-text-muted) !important;
font-size: 12px;
font-weight: 800;
line-height: 1.45;
}
.ledger-amount {
font-weight: 900;
text-align: right;
}
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 30px;
padding: 0 12px;
border-radius: var(--ds-radius-pill);
border: 1px solid rgba(217, 197, 168, 0.5);
background: rgba(255, 250, 243, 0.96);
color: #17392f;
font-size: 12px;
font-weight: 900;
}
.badge.badge-baron {
background: var(--ds-brand-soft-surface);
border-color: var(--ds-brand-soft-line);
color: var(--ds-brand-soft);
}
.badge.badge-family {
background: var(--ds-accent-soft-surface);
border-color: var(--ds-accent-soft-line);
color: var(--ds-status-warning);
}
.badge.ok {
background: var(--ds-success-soft);
border-color: var(--ds-success-line);
color: var(--ds-brand-soft);
}
.project-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0;
border: 0;
background: none;
color: #17392f;
font: inherit;
font-weight: 900;
text-align: left;
cursor: pointer;
}
.project-link:hover {
color: #0f6a55;
}
.member-form-label {
color: var(--ds-text-soft);
font-size: 12px;
font-weight: 900;
letter-spacing: 0.04em;
}
.member-form-input,
.member-form-select,
.member-form-time {
border: 1px solid var(--ds-line-soft);
border-radius: 16px;
background: rgba(255, 250, 243, 0.92);
color: var(--ds-ink);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.65);
}
.member-form-input:focus,
.member-form-select:focus,
.member-form-time:focus {
border-color: rgba(47, 153, 115, 0.45);
box-shadow: 0 0 0 4px rgba(47, 153, 115, 0.1);
}
.modal-btn {
min-height: 40px;
padding: 0 16px;
border-radius: var(--ds-radius-pill);
font-size: 12px;
font-weight: 900;
border: 1px solid transparent;
}
.modal-btn-cancel {
background: rgba(255, 250, 243, 0.96);
border-color: var(--ds-line);
color: var(--ds-text-soft);
}
.modal-btn-save {
background: var(--ds-brand-soft);
border-color: rgba(15, 58, 47, 0.22);
color: #fffaf3;
}
.modal-btn-delete {
background: rgba(169, 72, 50, 0.12);
border-color: rgba(169, 72, 50, 0.24);
color: var(--ds-status-danger);
}
.modal-btn-close {
background: rgba(242, 196, 132, 0.18);
border-color: rgba(214, 138, 58, 0.24);
color: var(--ds-status-warning);
}
.seatmap-actions .ghost-button {
min-height: 40px;
padding: 0 16px;
border-width: 1px;
border-style: solid;
border-radius: var(--ds-radius-pill);
font-size: 12px;
letter-spacing: -0.01em;
box-shadow: var(--ds-shadow-soft);
}
@media (max-width: 1180px) {
.project-head-grid {
grid-template-columns: 1fr;
}
.summary-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.project-meta-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 760px) {
.popup-wrap {
padding: 14px;
}
.summary-grid {
grid-template-columns: 1fr;
}
.ledger-head {
flex-direction: column;
align-items: flex-start;
}
.ledger-pill {
white-space: normal;
}
.ledger-table-wrap {
padding: 0 10px 12px;
overflow-x: auto;
}
}

View File

@@ -0,0 +1,60 @@
:root {
--ds-font-sans: "Pretendard", "Malgun Gothic", sans-serif;
--ds-bg: #f1eadf;
--ds-bg-soft: #f4e9d7;
--ds-bg-gradient:
radial-gradient(circle at top left, rgba(214, 138, 58, 0.18), transparent 24%),
radial-gradient(circle at top right, rgba(47, 153, 115, 0.12), transparent 22%),
linear-gradient(180deg, #f6efe6 0%, #f1eadf 100%);
--ds-panel: #fffaf3;
--ds-panel-soft: rgba(255, 250, 243, 0.9);
--ds-panel-strong: #eadcc4;
--ds-ink: #10251d;
--ds-text-soft: #425148;
--ds-text-muted: #66756d;
--ds-line: #d9c5a8;
--ds-line-soft: rgba(217, 197, 168, 0.45);
--ds-brand: #0f3a2f;
--ds-brand-deep: #0a2a22;
--ds-brand-soft: #1a5645;
--ds-accent: #d68a3a;
--ds-accent-soft: #f2c484;
--ds-accent-strong: #b66e22;
--ds-mint: #2f9973;
--ds-info: #4b87b3;
--ds-status-success: #2f6b52;
--ds-status-warning: #9a6422;
--ds-status-danger: #a94832;
--ds-surface-tint: rgba(255, 255, 255, 0.72);
--ds-surface-tint-strong: rgba(255, 255, 255, 0.88);
--ds-glass-dark: rgba(20, 45, 37, 0.34);
--ds-glass-dark-soft: rgba(16, 37, 29, 0.16);
--ds-glass-line: rgba(255, 255, 255, 0.14);
--ds-shadow-soft: 0 10px 24px rgba(15, 58, 47, 0.08);
--ds-shadow-card: 0 22px 54px rgba(15, 58, 47, 0.12);
--ds-shadow-float: 0 18px 36px rgba(15, 58, 47, 0.16);
--ds-shadow-hero: 0 28px 70px rgba(15, 58, 47, 0.22);
--ds-radius-sm: 8px;
--ds-radius-md: 12px;
--ds-radius-lg: 18px;
--ds-radius-xl: 24px;
--ds-radius-pill: 999px;
--ds-space-1: 4px;
--ds-space-2: 8px;
--ds-space-3: 12px;
--ds-space-4: 16px;
--ds-space-5: 20px;
--ds-space-6: 24px;
--ds-page-max-width: 2000px;
}

View File

@@ -12,8 +12,13 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Pretendard:wght@400;600;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/design-tokens.css?v=20260401-01">
<link rel="stylesheet" href="/design-patterns.css?v=20260401-01">
<link rel="stylesheet" href="/legacy/static/common.css">
<!-- Keep login and common hub defaults aligned with 8080. -->
<link rel="stylesheet" href="/styles.css?v=20260330-01">
<!-- 8081-only hub overrides must not restyle the login screen. -->
<link rel="stylesheet" href="/styles-8081-design.css?v=20260401-01">
</head>
<body>
<section id="login-panel" class="login-screen">
@@ -91,18 +96,26 @@
</header>
<main class="dashboard-main">
<section id="ledger-stage" class="main-stage" hidden>
<div class="stage-frame">
<iframe id="ledger-frame" src="/integrations/ledger?v=20260401-02" data-src="/integrations/ledger?v=20260401-02" title="사업관리대장 화면"></iframe>
</div>
</section>
<section id="organization-stage" class="main-stage">
<div class="stage-frame">
<iframe id="organization-frame" src="/legacy/organization?v=20260331-01" data-src="/legacy/organization?v=20260331-01" title="조직도 메인 화면"></iframe>
<!-- Legacy organization keeps its own CSS/JS responsibility under /legacy/static. -->
<iframe id="organization-frame" src="/legacy/organization?v=20260330-02" data-src="/legacy/organization?v=20260330-02" title="조직도 메인 화면"></iframe>
</div>
</section>
<section id="project-stage" class="main-stage" hidden>
<div class="stage-frame">
<!-- Integration HTML is served from incoming-files/served/payment.html. -->
<iframe id="project-frame" src="/integrations/payment" data-src="/integrations/payment" title="프로젝트별 분석 화면"></iframe>
</div>
</section>
<section id="team-stage" class="main-stage" hidden>
<div class="stage-frame">
<!-- Integration HTML is served from incoming-files/served/mh.html. -->
<iframe id="team-frame" src="/integrations/mh" data-src="/integrations/mh" title="팀/개인별 분석 화면"></iframe>
</div>
</section>
@@ -213,6 +226,6 @@
</main>
</section>
<script src="/app.js?v=20260330-01"></script>
<script src="/app.js?v=20260401-02"></script>
</body>
</html>

View File

@@ -0,0 +1,100 @@
.dashboard-header {
min-height: 68px;
background:
radial-gradient(circle at 12% 18%, rgba(242, 196, 132, 0.16), transparent 24%),
linear-gradient(145deg, rgba(10, 42, 34, 0.96) 0%, rgba(15, 58, 47, 0.96) 52%, rgba(26, 86, 69, 0.96) 100%);
color: #f7f0e4;
border-bottom: 1px solid rgba(242, 196, 132, 0.22);
backdrop-filter: blur(16px);
box-shadow: var(--ds-shadow-float);
}
.dashboard-header .eyebrow {
color: rgba(242, 196, 132, 0.94);
}
.dashboard-header h2 {
color: #fff7ea;
}
.nav-pill {
min-height: 42px;
padding: 0 14px;
border-radius: 999px;
border: 1px solid rgba(242, 196, 132, 0.28);
background: rgba(255, 255, 255, 0.08);
color: rgba(255, 244, 230, 0.78);
font-size: 14px;
font-weight: 800;
}
.nav-pill.active {
background: linear-gradient(180deg, rgba(255, 253, 248, 0.98), rgba(245, 235, 221, 0.94));
border-color: rgba(242, 196, 132, 0.34);
color: var(--ds-ink);
box-shadow: var(--ds-shadow-float);
}
.nav-pill.muted {
color: rgba(255, 244, 230, 0.48);
}
.nav-pill:hover {
color: #fff7ea;
border-color: rgba(242, 196, 132, 0.48);
}
.header-actions {
border-left: 1px solid rgba(242, 196, 132, 0.2);
}
.header-date-label {
color: rgba(255, 244, 230, 0.72);
}
.header-date-field {
border: 1px solid rgba(242, 196, 132, 0.22);
background: rgba(255, 255, 255, 0.1);
}
.header-date-field input,
.header-date-field select {
color: #fff7ea;
}
.header-date-sep {
color: rgba(255, 244, 230, 0.56);
}
.ghost-button {
border: 1px solid rgba(242, 196, 132, 0.22);
background: rgba(255, 255, 255, 0.08);
color: #fff7ea;
}
.icon-button {
background: rgba(255, 255, 255, 0.1);
}
.icon-button:hover {
background: rgba(242, 196, 132, 0.14);
border-color: rgba(242, 196, 132, 0.32);
color: #fff7ea;
}
.ghost-button-soft {
background: rgba(239, 228, 208, 0.92);
}
.seatmap-status[data-tone="error"] {
color: var(--ds-status-danger);
}
.seatmap-status[data-tone="success"] {
color: var(--ds-status-success);
}
.seatmap-board-wrap,
.seatmap-dxf-canvas {
background: var(--ds-panel);
}

View File

@@ -1,3 +1,30 @@
:root {
--color-bg: var(--ds-bg);
--color-surface: var(--ds-panel);
--color-surface-soft: var(--ds-panel-soft);
--color-surface-strong: var(--ds-panel-strong);
--color-text: var(--ds-ink);
--color-text-soft: var(--ds-text-soft);
--color-text-muted: var(--ds-text-muted);
--color-border: var(--ds-line);
--color-border-soft: var(--ds-line-soft);
--color-brand: var(--ds-brand);
--color-brand-deep: var(--ds-brand-deep);
--color-brand-soft: var(--ds-brand-soft);
--color-accent: var(--ds-accent);
--color-accent-soft: var(--ds-accent-soft);
--color-success: var(--ds-status-success);
--color-danger: var(--ds-status-danger);
--radius-sm: var(--ds-radius-sm);
--radius-md: var(--ds-radius-md);
--radius-lg: var(--ds-radius-lg);
--radius-xl: var(--ds-radius-xl);
--radius-pill: var(--ds-radius-pill);
--shadow-soft: var(--ds-shadow-soft);
--shadow-card: var(--ds-shadow-card);
--shadow-float: var(--ds-shadow-float);
}
.dashboard-shell,
.dashboard-main,
.main-stage,
@@ -31,7 +58,7 @@ body {
min-height: 100vh;
padding: 24px;
background:
linear-gradient(135deg, rgba(15, 23, 42, 0.42), rgba(30, 41, 59, 0.18)),
linear-gradient(135deg, rgba(10, 42, 34, 0.42), rgba(26, 86, 69, 0.18)),
url("https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&w=1800&q=80")
center center / cover no-repeat;
}
@@ -54,10 +81,10 @@ body {
display: grid;
grid-template-columns: 1.3fr 0.7fr;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.14);
border: 1px solid var(--ds-glass-line);
border-radius: var(--radius-lg);
background: rgba(71, 85, 105, 0.34);
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.24);
background: var(--ds-glass-dark);
box-shadow: var(--ds-shadow-hero);
backdrop-filter: blur(14px);
}
@@ -68,8 +95,8 @@ body {
padding: 30px 30px;
border-right: 1px solid rgba(255, 255, 255, 0.08);
background:
linear-gradient(90deg, rgba(15, 23, 42, 0.08), rgba(255, 255, 255, 0.02)),
linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(15, 23, 42, 0.08));
linear-gradient(90deg, rgba(10, 42, 34, 0.08), rgba(255, 255, 255, 0.02)),
linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(10, 42, 34, 0.08));
}
.login-brand .eyebrow {
@@ -83,7 +110,7 @@ body {
font-size: clamp(1.7rem, 3.2vw, 2.5rem);
line-height: 0.96;
letter-spacing: -0.04em;
color: #f8fafc;
color: #f7f0e4;
}
.login-form-wrap {
@@ -91,7 +118,7 @@ body {
display: grid;
align-content: center;
gap: 10px;
background: rgba(15, 23, 42, 0.12);
background: var(--ds-glass-dark-soft);
}
.login-card label {
@@ -140,8 +167,8 @@ body {
margin-top: 2px;
border: none;
color: #fff;
background: rgba(31, 41, 55, 0.82);
box-shadow: 0 14px 30px rgba(15, 23, 42, 0.22);
background: rgba(10, 42, 34, 0.82);
box-shadow: var(--shadow-float);
min-height: 34px;
border-radius: 999px;
font-size: 11px;
@@ -167,9 +194,9 @@ body {
.dashboard-header {
min-height: 68px;
background: rgba(255, 255, 255, 0.94);
background: rgba(255, 250, 243, 0.94);
color: var(--color-text);
border-bottom: 1px solid #d7dee8;
border-bottom: 1px solid var(--color-border);
display: flex;
align-items: center;
justify-content: space-between;
@@ -241,7 +268,7 @@ body {
border: none;
border-bottom: 3px solid transparent;
background: transparent;
color: #64748b;
color: var(--color-text-muted);
font-size: 15px;
font-weight: 700;
cursor: pointer;
@@ -255,7 +282,7 @@ body {
}
.nav-pill.muted {
color: #94a3b8;
color: rgba(102, 117, 109, 0.64);
}
.nav-pill:hover {
@@ -269,7 +296,7 @@ body {
gap: 6px;
position: relative;
padding-left: 18px;
border-left: 1px solid #dbe2ea;
border-left: 1px solid var(--color-border);
}
.header-date-controls {
@@ -284,7 +311,7 @@ body {
.header-date-label {
font-size: 12px;
font-weight: 800;
color: #64748b;
color: var(--color-text-muted);
}
.header-date-field {
@@ -292,9 +319,9 @@ body {
align-items: center;
min-height: 36px;
padding: 0 10px;
border: 1px solid #dbe2ea;
border: 1px solid var(--color-border);
border-radius: 999px;
background: #fff;
background: var(--color-surface);
}
.header-date-field input {
@@ -318,15 +345,15 @@ body {
}
.header-date-sep {
color: #94a3b8;
color: var(--color-text-muted);
font-size: 12px;
font-weight: 800;
}
.ghost-button {
min-height: 34px;
border: 1px solid #dbe2ea;
background: #fff;
border: 1px solid var(--color-border);
background: var(--color-surface);
color: var(--color-text);
padding: 0 12px;
border-radius: 999px;
@@ -342,12 +369,12 @@ body {
display: inline-flex;
align-items: center;
justify-content: center;
background: #f8fafc;
background: var(--color-surface-soft);
}
.icon-button:hover {
background: #f1f5f9;
border-color: #cbd5e1;
background: var(--ds-bg-soft);
border-color: var(--color-border);
color: var(--color-accent);
transform: translateY(-1px);
}
@@ -363,7 +390,7 @@ body {
}
.ghost-button-soft {
background: #f8fafc;
background: var(--color-surface-soft);
}
.user-chip {
@@ -381,8 +408,8 @@ body {
width: 18px;
height: 18px;
border-radius: 50%;
background: #e2e8f0;
color: #475569;
background: var(--color-surface-strong);
color: var(--color-text-soft);
font-size: 10px;
font-weight: 900;
flex: 0 0 auto;
@@ -421,10 +448,10 @@ body {
right: 0;
min-width: 220px;
padding: 14px;
border: 1px solid #dbe2ea;
border: 1px solid var(--color-border);
border-radius: 16px;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 18px 36px rgba(15, 23, 42, 0.14);
background: rgba(255, 250, 243, 0.96);
box-shadow: var(--shadow-float);
backdrop-filter: blur(12px);
z-index: 30;
}
@@ -440,7 +467,7 @@ body {
}
.user-popover-row + .user-popover-row {
border-top: 1px solid #eef2f7;
border-top: 1px solid rgba(217, 197, 168, 0.4);
}
.user-popover-label {
@@ -454,7 +481,7 @@ body {
min-height: 38px;
border: none;
border-radius: 12px;
background: #0f172a;
background: var(--color-brand);
color: #fff;
font-size: 11px;
font-weight: 800;
@@ -485,7 +512,7 @@ body {
width: 100%;
height: 100%;
border: 0;
background: #fff;
background: var(--color-surface);
}
.stage-empty {
@@ -502,9 +529,7 @@ body {
gap: 12px;
padding: 18px;
overflow: hidden;
background:
linear-gradient(180deg, rgba(248, 250, 252, 0.94), rgba(241, 245, 249, 0.92)),
radial-gradient(circle at top left, rgba(14, 165, 233, 0.1), transparent 32%);
background: var(--ds-bg-gradient);
}
.seatmap-topbar {
@@ -561,6 +586,54 @@ body {
display: none !important;
}
.seatmap-actions .ghost-button {
min-height: 40px;
padding: 0 16px;
border-width: 1px;
border-style: solid;
border-radius: var(--radius-pill);
font-size: 12px;
letter-spacing: -0.01em;
box-shadow: var(--shadow-soft);
}
#seatmap-admin-save-btn {
border-color: var(--color-brand-soft);
background: var(--color-brand-soft);
color: #fffaf3;
}
#seatmap-admin-save-btn:hover:not(:disabled) {
background: var(--color-brand);
border-color: var(--color-brand);
transform: translateY(-1px);
box-shadow: var(--shadow-float);
}
#seatmap-admin-save-btn:disabled {
opacity: 1;
cursor: not-allowed;
border-color: rgba(26, 86, 69, 0.24);
background: rgba(26, 86, 69, 0.18);
color: rgba(16, 37, 29, 0.72);
box-shadow: none;
}
#seatmap-admin-exit-btn,
#seatmap-readonly-exit-btn {
border-color: rgba(214, 138, 58, 0.48);
background: rgba(242, 196, 132, 0.22);
color: var(--color-brand-deep);
}
#seatmap-admin-exit-btn:hover,
#seatmap-readonly-exit-btn:hover {
background: rgba(242, 196, 132, 0.34);
border-color: rgba(182, 110, 34, 0.56);
color: var(--color-brand);
transform: translateY(-1px);
}
.seatmap-status {
min-height: 20px;
margin: 0;