From da635f22cefd0d68631db0f9d26a4cfcc4eadc3d Mon Sep 17 00:00:00 2001 From: king Date: Thu, 17 Sep 2026 13:59:30 +0900 Subject: [PATCH] =?UTF-8?q?feat(project):=20=ED=99=88=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=20=ED=97=A4=EB=8D=94=20=EC=83=89=EC=83=81=20=EC=B1=84=EC=9A=B0?= =?UTF-8?q?=EA=B8=B0,=20=EC=A2=8C=EC=B8=A1=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=EB=B0=94=20=ED=97=A4=EB=8D=94=20=EB=8C=80=EB=B9=84=20=EA=B0=95?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 프로젝트 카드: 이름 옆 작은 점 대신 카드 헤더 윗부분 전체를 프로젝트 색으로 채우고 글자 흰색(보드 세션 헤더와 같은 원칙). 액션 아이콘(업무추가/ 수정)도 흰색으로, "완료" 칩은 반투명 흰 배경으로 대비 확보. - 프로젝트 수정 후 DOM patch 로직도 새 구조(이름이 헤더 안, 설명은 본문 맨 앞)에 맞게 수정. - 좌측 "프로젝트"/"프로젝트 멤버"/"전체 멤버" 헤더 — 굵기만으론 12px 회색이라 여전히 흐려 보여서, 글자 색을 진한 잉크색으로 올려 대비 확보. Co-Authored-By: Claude Sonnet 5 --- .../project/templates/project/inbox.html | 2 +- .../project/templates/project/index.html | 11 ++++---- .../project/templates/project/project.html | 2 +- app/static/project.css | 25 +++++++++++++------ app/static/project.js | 8 +++--- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/app/modules/project/templates/project/inbox.html b/app/modules/project/templates/project/inbox.html index 276084e..4e2cc61 100644 --- a/app/modules/project/templates/project/inbox.html +++ b/app/modules/project/templates/project/inbox.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} diff --git a/app/modules/project/templates/project/index.html b/app/modules/project/templates/project/index.html index 6537bda..54bb1cb 100644 --- a/app/modules/project/templates/project/index.html +++ b/app/modules/project/templates/project/index.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + {% endblock %} @@ -22,11 +22,12 @@ data-status="{{ p.status or 'active' }}" data-creator="{{ p.created_by or '' }}"> - -
-
{{ p.name }} +
+ {{ p.name }} {% if p.status == 'completed' %}완료{% endif %} -
+ +
+
{% if p.description %}
{{ p.description }}
{% endif %} {% if p.members %}
diff --git a/app/modules/project/templates/project/project.html b/app/modules/project/templates/project/project.html index 2923bbf..cbc01de 100644 --- a/app/modules/project/templates/project/project.html +++ b/app/modules/project/templates/project/project.html @@ -1,7 +1,7 @@ {% extends "erp_base.html" %} {% block head_extra %} - + diff --git a/app/static/project.css b/app/static/project.css index 7f9b41f..d955a1f 100644 --- a/app/static/project.css +++ b/app/static/project.css @@ -68,26 +68,34 @@ .pj-project-card:hover { box-shadow: var(--pj-card-shadow-hover); transform: translateY(-1px); } .pj-project-card[draggable="true"] { cursor: grab; } .pj-project-card.is-dragging { opacity: .45; } -.pj-project-cardlink { display: flex; gap: 12px; padding: 16px; text-decoration: none; color: inherit; } +.pj-project-cardlink { display: flex; flex-direction: column; text-decoration: none; color: inherit; } +/* 카드 헤더 — 예전엔 이름 옆 작은 점(dot)이었지만, 이제 헤더 윗부분 전체를 + 프로젝트 색으로 채우고 글자는 흰색(세션 헤더 색칠과 같은 원칙). */ +.pj-project-header { + display: flex; align-items: center; padding: 12px 16px; + background: var(--pj-color, #4573d2); color: #fff; + border-radius: calc(var(--pj-card-radius) - 1px) calc(var(--pj-card-radius) - 1px) 0 0; +} +.pj-project-name .pj-chip { background: rgba(255,255,255,.28); color: #fff; } +.pj-project-body { padding: 12px 16px 16px; } /* 완료 프로젝트 — 비활성(흐리게) */ .pj-project-card.is-done { background: #f6f7f8; opacity: .62; } .pj-project-card.is-done:hover { opacity: .85; } -.pj-project-card.is-done .pj-project-dot { background: #9aa5b1; } -/* 카드 우측 상단 액션(업무 추가/수정) — 호버 시에만 노출 */ +/* 카드 우측 상단 액션(업무 추가/수정) — 헤더가 항상 색으로 채워지므로 + 흰 아이콘으로, 호버 시에만 노출 */ .pj-card-actions { position: absolute; top: 8px; right: 8px; display: flex; gap: 2px; } .pj-card-actions .pj-icon-btn { width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; - border-radius: 8px; color: #6b7280; opacity: 0; transition: opacity .12s; + border-radius: 8px; color: #fff; opacity: 0; transition: opacity .12s; } .pj-card-actions .pj-icon-btn .material-symbols-outlined { font-size: 18px; } .pj-project-card:hover .pj-card-actions .pj-icon-btn { opacity: 1; } -.pj-card-actions .pj-icon-btn:hover { background: #eceef0; color: #1e1f21; } -.pj-project-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--pj-color, #4573d2); margin-top: 5px; flex: 0 0 auto; } +.pj-card-actions .pj-icon-btn:hover { background: rgba(255,255,255,.25); color: #fff; } .pj-project-name { font-weight: 700; font-size: 15px; } -.pj-project-desc { color: #6b7280; font-size: 12.5px; margin-top: 3px; } +.pj-project-desc { color: #6b7280; font-size: 12.5px; } /* 프로젝트 이름 아래 — 배정 멤버(아이콘+이름) */ .pj-project-members { display: flex; flex-wrap: wrap; gap: 3px 10px; margin-top: 6px; } .pj-project-member { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; color: #6b7280; } @@ -204,6 +212,9 @@ .pj-side-block { margin-bottom: 22px; } .pj-side-head { display: flex; align-items: center; justify-content: space-between; font-size: 12px; font-weight: 800; color: #6b7280; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; } +/* 굵게 지정해도 연한 회색 + 12px 라서 눈에 잘 안 띄었음 — 텍스트만 진한 + 잉크색으로 대비를 올린다("+" 버튼은 원래 색 유지). */ +.pj-side-head span { color: var(--pj-ink); } .pj-member-list { list-style: none; margin: 0; padding: 0; } .pj-member-list li { display: flex; align-items: center; gap: 8px; padding: 5px 4px; border-radius: 7px; } .pj-member-list li:hover { background: #f6f7f8; } diff --git a/app/static/project.js b/app/static/project.js index 19c96f2..347e8a7 100644 --- a/app/static/project.js +++ b/app/static/project.js @@ -518,7 +518,10 @@ if (!descEl) { descEl = document.createElement("div"); descEl.className = "pj-project-desc"; - if (nameEl) nameEl.insertAdjacentElement("afterend", descEl); + // 이름은 이제 색칠된 헤더 안에 있으므로(afterend 로 넣으면 헤더 + // 안에 끼어버림), 본문(.pj-project-body) 맨 앞에 넣는다. + const body = card.querySelector(".pj-project-body"); + if (body) body.insertBefore(descEl, body.firstChild); } descEl.textContent = p.description; } else if (descEl) descEl.remove(); @@ -556,9 +559,8 @@ ' data-start="' + (p.start_date || "") + '" data-due="' + (p.due_date || "") + '"' + ' data-color="' + color + '" data-status="active" data-creator="' + escapeHtml(p.created_by || "") + '">' + '' + - '' + + '
' + escapeHtml(p.name || "") + "
" + '
' + - '
' + escapeHtml(p.name || "") + "
" + (p.description ? '
' + escapeHtml(p.description) + "
" : "") + '
' + (p.due_date ? '마감 ' + fmtDateKr(p.due_date) + "" : "") +