diff --git a/resources/views/rd/org-chart.blade.php b/resources/views/rd/org-chart.blade.php index 023c6fe5..4f66f9fe 100644 --- a/resources/views/rd/org-chart.blade.php +++ b/resources/views/rd/org-chart.blade.php @@ -3,7 +3,7 @@ @section('title', '조직도 관리') @section('content') -
+

@@ -19,7 +19,7 @@
- 직원 카드를 드래그하여 부서에 배치합니다. 부서 헤더를 드래그하여 순서를 변경하거나 다른 부서 아래로 이동할 수 있습니다. + 직원 카드를 드래그하여 부서에 배치합니다. 부서 헤더를 드래그하여 순서를 변경하거나 다른 부서 아래로 이동할 수 있습니다. 부서 헤더를 더블클릭하면 숨기기 버튼이 나타납니다.
@@ -43,6 +43,28 @@ class="px-3 py-1 border border-gray-200 rounded text-xs focus:outline-none focus

+ +
+
+
+ + 숨겨진 부서 + +
+
+ +
+
+
+
@@ -105,6 +127,8 @@ function orgChart() { deptSortables: [], empSortables: [], unassignedSortable: null, + hiddenDepts: new Set(), + dblClickDept: null, get totalEmployees() { return this.employees.length; }, get assignedCount() { return this.employees.filter(e => e.department_id).length; }, @@ -187,7 +211,7 @@ function orgChart() { }, buildChildrenHtml(parentId, level) { - const children = this.getChildrenSorted(parentId); + const children = this.getChildrenSorted(parentId).filter(d => !this.isDeptHidden(d.id)); if (!children.length && parentId !== null) { return `
하위 부서 드롭
`; } @@ -212,11 +236,14 @@ function orgChart() { let h = `
`; h += `
`; h += `
`; - h += `
`; + h += `
`; h += ``; h += ``; h += `${this.esc(dept.name)}`; if (dept.code) h += `(${this.esc(dept.code)})`; + if (this.dblClickDept === dept.id) { + h += ``; + } h += '
'; h += `
`; if (emps.length) { @@ -343,13 +370,52 @@ function orgChart() { handleClick(e) { const btn = e.target.closest('[data-action]'); - if (!btn) return; + if (!btn) { + if (this.dblClickDept !== null) { this.dblClickDept = null; this.renderTree(); } + return; + } if (btn.dataset.action === 'unassign') { e.preventDefault(); this.unassignEmployee(parseInt(btn.dataset.empId)); + } else if (btn.dataset.action === 'hide-dept') { + e.preventDefault(); e.stopPropagation(); + this.hideDept(parseInt(btn.dataset.deptId)); + } else if (btn.dataset.action === 'restore-dept') { + e.preventDefault(); + this.restoreDept(parseInt(btn.dataset.deptId)); } }, + handleDblClick(e) { + const header = e.target.closest('[data-action="dept-dblclick"]'); + if (!header) return; + e.preventDefault(); + const deptId = parseInt(header.dataset.deptId); + this.dblClickDept = this.dblClickDept === deptId ? null : deptId; + this.renderTree(); + }, + + isDeptHidden(deptId) { + if (this.hiddenDepts.has(deptId)) return true; + const dept = this.departments.find(d => d.id === deptId); + return dept && dept.parent_id ? this.isDeptHidden(dept.parent_id) : false; + }, + + hideDept(deptId) { + this.hiddenDepts.add(deptId); + this.dblClickDept = null; + this.renderTree(); + }, + + restoreDept(deptId) { + this.hiddenDepts.delete(deptId); + this.renderTree(); + }, + + get hiddenDeptList() { + return this.departments.filter(d => this.hiddenDepts.has(d.id)); + }, + async saveAssignment(empId, deptId) { this.saving = true; try {