From b83654ba2546f4ef3fcb95d721ad80d9a225f6e6 Mon Sep 17 00:00:00 2001 From: Hyungi Ahn Date: Mon, 15 Sep 2025 11:43:43 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=93=B1=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EA=B0=84=EC=86=8C=ED=99=94=20=EB=B0=8F=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 핵심 변경사항: ✅ 간단한 프로젝트 등록 요청 시스템으로 변경 - 복잡한 2단계 시스템 → 간단한 요청 폼으로 단순화 - 필수 입력 항목만 4개로 축소 📋 새로운 입력 항목 (4개만) 1. 프로젝트명 * 2. 고객사 정보 (엔드유저 * + EPC/실제고객사) 3. 납기일 * 4. 납품방식 * (현장납품/공장인도/부분납품) 🎯 Job No. 자동 생성 시스템 - TK-년도-순번 규칙 (예: TK-2024-156) - 실시간 미리보기 기능 - 등록 승인 후 자동 부여 🎨 UI/UX 개선 - 좌측: 간단한 등록 폼 - 우측: 최근 등록 요청 현황 리스트 - 상태별 색상 구분 (승인완료/검토중/추가정보필요) - 반응형 디자인 (모바일 지원) ⚡ 인터랙티브 기능 - 실시간 Job No. 미리보기 - 폼 검증 및 제출 처리 - 새 요청 자동 리스트 추가 - 애니메이션 효과 (fade-in, slide-in) - 초기화 버튼 기능 💾 하드코딩 데이터 - 기존 요청 3개 (승인완료/검토중/보류) - 실제 업무 시나리오 반영 - 다양한 고객사 유형 (엔드유저 vs EPC) 시연 준비: 간단하고 직관적인 프로젝트 등록 시스템 완성 --- .DS_Store | Bin 0 -> 6148 bytes demo/index.html | 169 +++++++++++++++++--------------- demo/scripts/main.js | 151 +++++++++++++++++++++++++++-- demo/styles/devonthink.css | 193 +++++++++++++++++++++++++++++++++++++ 4 files changed, 425 insertions(+), 88 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..02c5aecf6d8661f9ef84faea22669366e0dc7f0d GIT binary patch literal 6148 zcmeHKy>8S%5T3nUh))sd3P7PiT8Z`)oInC7jX6SrXb_G_0mz)=156xm4v%rs}u%z1O(y!SMGsj9H-mBT@|S3K6%hEiF4IPb-e(tZ`S&)-pb*-P_& zVG`1$kB}#uX`ZO6tA=?pFu9>!@LFCgYF`?SmT#_hG+GZLH8-52UL)vS0HDLO4ysQ z3fiXUlwnrUB1lW7NfVcm|0`+d_P>7qey~T;m*M`mcm9XBsI&4(o|H?skL1E+VFs81 zX5cg!a7Uvze;UQPCNsbc{L>8R^Fcy21`cbB=IFp+S^!`ZZX=kRUw@#~4q)K0wg?YI z*i@iR6|Th)u5%DJ9qWOMuPxei66VRM5m@Ar8DIvc8JMwVTi^e8 zf8YO4C$Ys0Fa!S;1ERSeu6MB|ceftfoW5%%^chr(j;k$BQZO-BF=F*qyZ|)
-
- +
-

1단계: 프로젝트 생성

- 진행중 +

프로젝트 기본 정보

+ 신규 등록
-
+
- +
-
- - + +
+

고객사 정보

+
+
+ + +
+
+ + +
+
-
- - + +
+
+
+ + +
+
+ + +
+
-
- - + +
+
+ 생성될 Job No. (예시) + TK-2024-XXX +
+
+ * Job No.는 등록 승인 후 자동으로 부여됩니다 (TK-년도-순번) +
-
- - -
-
- - + +
+ +
- -
-
- 자동 생성된 Job No. - TK-2024-015 -
-
- -
- +
-

2단계: 세부 사양 입력

- 선택적 +

최근 등록 요청 현황

-
-

킥오프 미팅 결과

-
-
- 미팅 일자 - 2024-01-20 +
+
+
+
ABC 공장 배관공사
+
+ ABC 케미칼 + 현장납품 + 납기: 2024-03-30 +
-
- 참석자 - 김영업, 이PM, 박설계, 최고객 +
+ 승인완료 + TK-2024-015
-
-
주요 결정사항
-
    -
  • 압력등급 150LB로 확정
  • -
  • 재질 SS316L로 변경
  • -
+ +
+
+
DEF 플랜트 배관 설치
+
+ DEF 화학 + 공장인도 + 납기: 2024-04-15 +
+
+
+ 검토중 + 대기중 +
-
- -
-

기술 사양서

-
-
- 설계기준 - ASME B31.3 + +
+
+
GHI 정유 공장 개보수
+
+ GHI 정유 / 한국엔지니어링 + 부분납품 + 납기: 2024-05-20 +
-
- 사용압력 - 10 bar -
-
- 사용온도 - 80°C -
-
- 유체 - 화학용매 +
+ 추가정보 필요 + 보류
- -
diff --git a/demo/scripts/main.js b/demo/scripts/main.js index de9f369..6fc663b 100644 --- a/demo/scripts/main.js +++ b/demo/scripts/main.js @@ -355,15 +355,147 @@ function initializePage(pageId) { function initializeProjectRegistration() { console.log('프로젝트 등록 페이지 초기화'); - // 자동 생성된 Job No. 애니메이션 - const jobNoValue = document.querySelector('.generated-item .value'); - if (jobNoValue) { - setTimeout(() => { - jobNoValue.style.transform = 'scale(1.1)'; - setTimeout(() => { - jobNoValue.style.transform = 'scale(1)'; - }, 200); - }, 500); + // 폼 이벤트 리스너 설정 + setupProjectForm(); + + // Job No. 미리보기 업데이트 + updateJobNoPreview(); + + // 요청 리스트 애니메이션 + animateElements('.request-item'); +} + +// 프로젝트 폼 설정 +function setupProjectForm() { + const form = document.querySelector('.project-form'); + if (!form) return; + + // 폼 제출 이벤트 + form.addEventListener('submit', function(e) { + e.preventDefault(); + handleProjectSubmission(); + }); + + // 입력 필드 변경시 Job No. 미리보기 업데이트 + const inputs = form.querySelectorAll('input, select'); + inputs.forEach(input => { + input.addEventListener('input', updateJobNoPreview); + }); +} + +// 프로젝트 제출 처리 +function handleProjectSubmission() { + const form = document.querySelector('.project-form'); + const formData = new FormData(form); + + // 입력값 검증 + const projectName = document.getElementById('project-name').value; + const endUser = document.getElementById('end-user').value; + const deliveryDate = document.getElementById('delivery-date').value; + const deliveryMethod = document.getElementById('delivery-method').value; + + if (!projectName || !endUser || !deliveryDate || !deliveryMethod) { + showNotification('필수 항목을 모두 입력해주세요.', 'warning'); + return; + } + + // 제출 버튼 상태 변경 + const submitBtn = document.getElementById('submit-btn'); + const originalText = submitBtn.textContent; + submitBtn.textContent = '📤 요청 중...'; + submitBtn.disabled = true; + + // 가상 제출 처리 (2초 후 완료) + setTimeout(() => { + // 새로운 Job No. 생성 + const newJobNo = generateJobNo(); + + // 성공 메시지 + showNotification(`프로젝트 등록 요청이 완료되었습니다! (예상 Job No: ${newJobNo})`, 'success'); + + // 요청 리스트에 새 항목 추가 + addNewRequestToList(projectName, endUser, deliveryDate, deliveryMethod); + + // 폼 초기화 + clearForm(); + + // 버튼 복원 + submitBtn.textContent = originalText; + submitBtn.disabled = false; + + }, 2000); +} + +// Job No. 생성 +function generateJobNo() { + const year = new Date().getFullYear(); + const randomNum = Math.floor(Math.random() * 900) + 100; // 100-999 + return `TK-${year}-${randomNum}`; +} + +// Job No. 미리보기 업데이트 +function updateJobNoPreview() { + const projectName = document.getElementById('project-name')?.value; + const previewElement = document.getElementById('preview-job-no'); + + if (!previewElement) return; + + if (projectName && projectName.length > 0) { + const year = new Date().getFullYear(); + const nextNum = String(Math.floor(Math.random() * 900) + 100); + previewElement.textContent = `TK-${year}-${nextNum}`; + previewElement.style.color = 'var(--dt-primary)'; + } else { + previewElement.textContent = 'TK-2024-XXX'; + previewElement.style.color = 'var(--dt-gray-500)'; + } +} + +// 새 요청을 리스트에 추가 +function addNewRequestToList(projectName, endUser, deliveryDate, deliveryMethod) { + const requestList = document.querySelector('.request-list'); + if (!requestList) return; + + const epcCustomer = document.getElementById('epc-customer')?.value; + const customerText = epcCustomer ? `${endUser} / ${epcCustomer}` : endUser; + + const newItem = document.createElement('div'); + newItem.className = 'request-item status-pending'; + newItem.innerHTML = ` +
+
${projectName}
+
+ ${customerText} + ${deliveryMethod} + 납기: ${deliveryDate} +
+
+
+ 검토중 + 대기중 +
+ `; + + // 리스트 맨 위에 추가 + requestList.insertBefore(newItem, requestList.firstChild); + + // 애니메이션 + newItem.style.opacity = '0'; + newItem.style.transform = 'translateY(-20px)'; + + setTimeout(() => { + newItem.style.transition = 'all 0.3s ease'; + newItem.style.opacity = '1'; + newItem.style.transform = 'translateY(0)'; + }, 100); +} + +// 폼 초기화 +function clearForm() { + const form = document.querySelector('.project-form'); + if (form) { + form.reset(); + updateJobNoPreview(); } } @@ -637,5 +769,6 @@ window.showPage = showPage; window.showModal = showModal; window.hideModal = hideModal; window.showNotification = showNotification; +window.clearForm = clearForm; console.log('TK Project Demo JavaScript 로드 완료'); diff --git a/demo/styles/devonthink.css b/demo/styles/devonthink.css index 903e897..b1f1ad0 100644 --- a/demo/styles/devonthink.css +++ b/demo/styles/devonthink.css @@ -382,6 +382,199 @@ body { } } +/* 프로젝트 등록 컨테이너 */ +.project-registration-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 24px; + max-width: 1200px; +} + +@media (max-width: 1000px) { + .project-registration-container { + grid-template-columns: 1fr; + } +} + +/* 프로젝트 폼 */ +.project-form { + display: flex; + flex-direction: column; + gap: 24px; +} + +.customer-section, .delivery-section { + padding: 20px; + background-color: var(--dt-gray-50); + border-radius: 8px; + border: 1px solid var(--dt-gray-200); +} + +.customer-section h4, .delivery-section h4 { + font-size: 16px; + font-weight: 600; + color: var(--dt-gray-800); + margin-bottom: 16px; +} + +.customer-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} + +@media (max-width: 600px) { + .customer-grid { + grid-template-columns: 1fr; + } +} + +.form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} + +@media (max-width: 600px) { + .form-row { + grid-template-columns: 1fr; + } +} + +/* 자동 생성 미리보기 */ +.generated-preview { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; +} + +.generated-preview .label { + font-size: 14px; + color: var(--dt-gray-600); + font-weight: 500; +} + +.generated-preview .value { + font-size: 16px; + font-weight: 700; + color: var(--dt-gray-500); + font-family: 'Monaco', 'Menlo', monospace; +} + +.generation-rule { + font-size: 12px; + color: var(--dt-gray-500); + font-style: italic; +} + +/* 폼 액션 */ +.form-actions { + display: flex; + gap: 12px; + justify-content: flex-end; + padding-top: 20px; + border-top: 1px solid var(--dt-gray-200); +} + +@media (max-width: 600px) { + .form-actions { + flex-direction: column; + } +} + +/* 요청 리스트 */ +.request-list { + display: flex; + flex-direction: column; + gap: 12px; +} + +.request-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + border: 1px solid var(--dt-gray-200); + border-radius: 8px; + background-color: var(--dt-gray-50); + transition: all 0.2s ease; +} + +.request-item:hover { + background-color: white; + box-shadow: var(--dt-shadow); +} + +.request-item.status-approved { + border-left: 4px solid var(--dt-success); +} + +.request-item.status-pending { + border-left: 4px solid var(--dt-warning); +} + +.request-item.status-review { + border-left: 4px solid var(--dt-danger); +} + +.request-title { + font-size: 16px; + font-weight: 600; + color: var(--dt-gray-800); + margin-bottom: 6px; +} + +.request-details { + display: flex; + gap: 12px; + flex-wrap: wrap; + font-size: 12px; + color: var(--dt-gray-600); +} + +.request-details span { + padding: 2px 8px; + background-color: white; + border-radius: 12px; + border: 1px solid var(--dt-gray-200); +} + +.request-status { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 6px; +} + +.job-no { + font-size: 12px; + font-weight: 700; + color: var(--dt-primary); + font-family: 'Monaco', 'Menlo', monospace; +} + +/* 상태별 스타일 */ +.status-warning { + background-color: var(--dt-danger); + color: white; +} + +@media (max-width: 600px) { + .request-item { + flex-direction: column; + align-items: flex-start; + gap: 12px; + } + + .request-status { + align-items: flex-start; + flex-direction: row; + justify-content: space-between; + width: 100%; + } +} + /* 자동 생성 정보 */ .auto-generated { margin: 20px 0;