feat(org-chart): add core cards and fixed-layout integration
This commit is contained in:
1 parent
d18e3c3380
commit
61c6f8d1f1
161 files changed
+13044
-1
No files matched your search
@@ -0,0 +1,56 @@
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
|
||||
// Organization names were observed on Workdesk. Membership, employees and
|
||||
// every count below are synthetic, not an export of production HR data.
|
||||
const groups = [
|
||||
['business-management', '사업관리', 'office', []],
|
||||
['business-planning', '경영기획', 'office', ['경영기획 셀', '사업관리 셀']],
|
||||
['talent-growth', '인재성장', 'office', ['HR기획 셀', '자산관리 셀']],
|
||||
['integrated-system', '통합시스템 Div', 'div', ['IS 1팀', 'IS 2팀', 'IS 3팀']],
|
||||
['design-planning', '디자인기획', 'office', ['UX 셀', '영상 셀', '편집 셀']],
|
||||
['solution-sales', '솔루션영업', 'office', ['S/W 셀']],
|
||||
];
|
||||
const affiliations = [
|
||||
['hanmac', '(주)한맥기술'], ['saman', '(주)삼안'], ['jangheon', '(주)장헌'],
|
||||
['jangheon-industry', '장헌산업'], ['ptc', 'PTC'], ['halla', '한라산업개발'], ['baron', '바론컨설턴트'],
|
||||
].map(([id, name]) => ({ id, name }));
|
||||
const organizations = [{ id: 'general-planning', parentId: null, name: '총괄기획실', type: 'root', leaderId: 'mock-leader-00', displayOrder: 0 }];
|
||||
// Invented display names only; never sourced from a Workdesk employee capture.
|
||||
const names = [
|
||||
'김솔', '이도윤', '박하준', '정지우', '최예린', '한준서', '오수아',
|
||||
'강민서', '윤시우', '서다은', '배지안', '임서준', '송하린', '조유찬',
|
||||
'신도하', '문예은', '권지호', '안채원', '유시온', '홍서아', '고은우',
|
||||
'남하윤', '백도현', '노유나', '장태오', '양서진', '진서율', '구민재',
|
||||
'전하은', '심이준', '차소율', '우지율', '손예준', '함다온', '허지유',
|
||||
'황서우', '성유빈', '곽지후', '류다인', '하주원', '이봄',
|
||||
];
|
||||
const employees = [{ id: 'mock-leader-00', organizationId: 'general-planning', affiliationId: 'hanmac', name: names[0], position: '경영진', jobTitle: '실장', profileImage: null, workStatus: 'active' }];
|
||||
let person = 1;
|
||||
for (const [index, [id, name, type, cells]] of groups.entries()) {
|
||||
const leaderId = `mock-leader-${String(index + 1).padStart(2, '0')}`;
|
||||
organizations.push({ id, parentId: 'general-planning', name, type, leaderId, displayOrder: index });
|
||||
employees.push({ id: leaderId, organizationId: id, affiliationId: ['hanmac', 'saman', 'baron'][index % 3], name: names[employees.length], position: '수석', jobTitle: type === 'div' ? '디비전장' : '팀장', profileImage: null, workStatus: 'active' });
|
||||
const employeeOrganizations = cells.length ? cells.map((cell, cellIndex) => {
|
||||
const childId = `${id}-${cellIndex + 1}`;
|
||||
organizations.push({ id: childId, parentId: id, name: cell, type: cell.includes('팀') ? 'team' : 'cell', leaderId: null, displayOrder: cellIndex });
|
||||
return childId;
|
||||
}) : [id];
|
||||
for (const childId of employeeOrganizations) for (let member = 0; member < (cells.length ? 3 : 1); member++) {
|
||||
const employeeId = `mock-employee-${String(person).padStart(2, '0')}`;
|
||||
const isTeamLeader = childId.startsWith('integrated-system-') && member === 0;
|
||||
employees.push({ id: employeeId, organizationId: childId, affiliationId: ['hanmac', 'saman', 'ptc', 'baron'][person % 4], name: names[employees.length], position: ['책임', '선임', '연구'][member % 3], jobTitle: isTeamLeader ? '팀장' : null, profileImage: null, workStatus: person === 3 ? 'dispatched' : person === 25 ? 'onLeave' : 'active' });
|
||||
if (isTeamLeader) organizations.find(item => item.id === childId).leaderId = employeeId;
|
||||
person++;
|
||||
}
|
||||
}
|
||||
const fixture = {
|
||||
schemaVersion: '0.1-draft', organizations, employees, affiliations, relations: [],
|
||||
presentation: {
|
||||
title: '총괄기획실 조직도', description: '실제 조직명 · 가상 직원 정보 및 인원 통계 · 운영 인원수가 아닙니다.', hubText: '협업 · 소통 허브',
|
||||
groups: { showEmployees: true, showSummary: true, showDispatched: true, showOnLeave: true, showAffiliations: true },
|
||||
organizationOrder: ['general-planning', ...groups.map(([id]) => id)],
|
||||
},
|
||||
metadata: { asOfDate: '2026-10-12', dataVersion: 'p1-virtual-employees-v1', updateNote: '운영 HR 정보와 무관한 가상 구성' },
|
||||
};
|
||||
await writeFile(new URL('./data-p1.json', import.meta.url), `${JSON.stringify(fixture, null, 2)}\n`);
|
||||
console.log(`P1 fixture: ${organizations.length} organizations / ${employees.length} synthetic employees`);
|
||||
Reference in new issue
Block a user