645 lines
25 KiB
TypeScript
645 lines
25 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
import { FileText, Plus, Trash2, X, Loader2, ChevronDown, Search } from 'lucide-react';
|
|
import { createPortal } from 'react-dom';
|
|
import { JobReportItem, CommonCode } from '@/types';
|
|
import { JobTypeSelectModal } from './JobTypeSelectModal';
|
|
import { ProjectSearchDialog } from './ProjectSearchDialog';
|
|
import { comms } from '@/communication';
|
|
|
|
export interface JobreportFormData {
|
|
pdate: string;
|
|
projectName: string;
|
|
pidx: number | null; // 프로젝트 인덱스 (-1이면 프로젝트 연결 없음)
|
|
requestpart: string;
|
|
package: string;
|
|
type: string;
|
|
process: string;
|
|
status: string;
|
|
description: string;
|
|
hrs: number;
|
|
ot: number;
|
|
otStart: string; // 초과근무 시작시간 (HH:mm 형식)
|
|
otEnd: string; // 초과근무 종료시간 (HH:mm 형식)
|
|
jobgrp: string;
|
|
tag: string;
|
|
}
|
|
|
|
// 날짜 포맷 헬퍼 함수 (로컬 시간 기준)
|
|
const formatDateLocal = (date: Date) => {
|
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
|
};
|
|
|
|
export const initialFormData: JobreportFormData = {
|
|
pdate: formatDateLocal(new Date()),
|
|
projectName: '',
|
|
pidx: null,
|
|
requestpart: '',
|
|
package: '',
|
|
type: '',
|
|
process: '',
|
|
status: '진행 완료',
|
|
description: '',
|
|
hrs: 8,
|
|
ot: 0,
|
|
otStart: '18:00',
|
|
otEnd: '20:00',
|
|
jobgrp: '',
|
|
tag: '',
|
|
};
|
|
|
|
interface JobreportEditModalProps {
|
|
isOpen: boolean;
|
|
editingItem: JobReportItem | null;
|
|
formData: JobreportFormData;
|
|
processing: boolean;
|
|
onClose: () => void;
|
|
onFormChange: (data: JobreportFormData) => void;
|
|
onSave: () => void;
|
|
onDelete: (idx: number) => void;
|
|
}
|
|
|
|
export function JobreportEditModal({
|
|
isOpen,
|
|
editingItem,
|
|
formData,
|
|
processing,
|
|
onClose,
|
|
onFormChange,
|
|
onSave,
|
|
onDelete,
|
|
}: JobreportEditModalProps) {
|
|
const [showJobTypeModal, setShowJobTypeModal] = useState(false);
|
|
const [showProjectSearch, setShowProjectSearch] = useState(false);
|
|
const [requestPartList, setRequestPartList] = useState<CommonCode[]>([]);
|
|
const [packageList, setPackageList] = useState<CommonCode[]>([]);
|
|
const [processList, setProcessList] = useState<CommonCode[]>([]);
|
|
const [statusList, setStatusList] = useState<CommonCode[]>([]);
|
|
const [loadingCodes, setLoadingCodes] = useState(false);
|
|
// 프로젝트 변경 추적 (이전 기록 불러오기 여부 판단)
|
|
const [previousProjectIdx, setPreviousProjectIdx] = useState<number | null>(null);
|
|
|
|
// ESC 키로 닫기
|
|
useEffect(() => {
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
if (e.key === 'Escape' && isOpen && !showJobTypeModal && !showProjectSearch) {
|
|
onClose();
|
|
}
|
|
};
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [isOpen, onClose, showJobTypeModal, showProjectSearch]);
|
|
|
|
// 공용코드 로드 (WebSocket에서 동일 응답타입 충돌 방지를 위해 순차 로드)
|
|
const loadCommonCodes = useCallback(async () => {
|
|
setLoadingCodes(true);
|
|
try {
|
|
// WebSocket 모드에서는 같은 응답타입을 사용하므로 순차적으로 로드
|
|
const requestPart = await comms.getCommonList('13'); // 요청부서
|
|
setRequestPartList(requestPart || []);
|
|
|
|
const packages = await comms.getCommonList('14'); // 패키지
|
|
setPackageList(packages || []);
|
|
|
|
const processes = await comms.getCommonList('16'); // 공정(프로세스)
|
|
setProcessList(processes || []);
|
|
|
|
const statuses = await comms.getCommonList('12'); // 상태
|
|
setStatusList(statuses || []);
|
|
} catch (error) {
|
|
console.error('공용코드 로드 오류:', error);
|
|
} finally {
|
|
setLoadingCodes(false);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
loadCommonCodes();
|
|
}
|
|
}, [isOpen, loadCommonCodes]);
|
|
|
|
// 모달 열릴 때 프로젝트가 설정되어 있으면 자동으로 최종 설정 불러오기
|
|
useEffect(() => {
|
|
const loadLastSettings = async () => {
|
|
// 신규 등록이고, 프로젝트가 설정되어 있으며, 기본값이 비어있는 경우에만 자동 로드
|
|
if (isOpen && !editingItem && formData.pidx && formData.pidx > 0) {
|
|
// 이미 설정된 값이 있으면 자동 로드하지 않음 (복사 기능 등에서 이미 값이 있을 수 있음)
|
|
const hasExistingSettings = formData.requestpart || formData.package || formData.type || formData.process;
|
|
if (hasExistingSettings) {
|
|
setPreviousProjectIdx(formData.pidx);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const lastReport = await comms.getLastJobReportByProject(formData.pidx, formData.projectName);
|
|
if (lastReport.Success && lastReport.Data) {
|
|
const updatedFormData = { ...formData };
|
|
|
|
if (lastReport.Data.requestpart) {
|
|
updatedFormData.requestpart = lastReport.Data.requestpart;
|
|
}
|
|
if (lastReport.Data.package) {
|
|
updatedFormData.package = lastReport.Data.package;
|
|
}
|
|
if (lastReport.Data.type) {
|
|
updatedFormData.type = lastReport.Data.type;
|
|
}
|
|
if (lastReport.Data.jobgrp) {
|
|
updatedFormData.jobgrp = lastReport.Data.jobgrp;
|
|
}
|
|
if (lastReport.Data.process) {
|
|
updatedFormData.process = lastReport.Data.process;
|
|
}
|
|
if (lastReport.Data.status) {
|
|
updatedFormData.status = lastReport.Data.status;
|
|
}
|
|
|
|
onFormChange(updatedFormData);
|
|
}
|
|
setPreviousProjectIdx(formData.pidx);
|
|
} catch (error) {
|
|
console.error('최종 설정 불러오기 오류:', error);
|
|
setPreviousProjectIdx(formData.pidx);
|
|
}
|
|
} else if (isOpen && !editingItem) {
|
|
// 신규 등록인데 프로젝트가 없으면 초기화
|
|
setPreviousProjectIdx(null);
|
|
}
|
|
};
|
|
|
|
loadLastSettings();
|
|
}, [isOpen, editingItem]);
|
|
|
|
if (!isOpen) return null;
|
|
|
|
const handleFieldChange = <K extends keyof JobreportFormData>(
|
|
field: K,
|
|
value: JobreportFormData[K]
|
|
) => {
|
|
onFormChange({ ...formData, [field]: value });
|
|
};
|
|
|
|
// 업무형태 선택 처리
|
|
const handleJobTypeSelect = (process: string, jobgrp: string, type: string) => {
|
|
// WinForms과 동일하게 N/A 처리: jobgrp만 N/A 처리, process는 빈 값 허용
|
|
const normalizedJobgrp = (!jobgrp || jobgrp === '(N/A)') ? 'N/A' : jobgrp;
|
|
// process가 N/A면 빈 문자열로 (공정 드롭다운에서 선택하도록)
|
|
const normalizedProcess = (process === 'N/A') ? '' : process;
|
|
|
|
onFormChange({
|
|
...formData,
|
|
process: normalizedProcess || formData.process, // process가 없으면 기존 값 유지
|
|
jobgrp: normalizedJobgrp,
|
|
type,
|
|
});
|
|
};
|
|
|
|
// 업무형태 표시 텍스트 (type ← jobgrp 형태, WinForms과 동일)
|
|
const getJobTypeDisplayText = () => {
|
|
if (!formData.type) {
|
|
return '업무형태를 선택하세요';
|
|
}
|
|
|
|
// WinForms: fullname = $"{jtype} ← {jgrp}"
|
|
if (formData.jobgrp && formData.jobgrp !== 'N/A') {
|
|
return `${formData.type} ← ${formData.jobgrp}`;
|
|
}
|
|
|
|
return formData.type;
|
|
};
|
|
|
|
// 유효성 검사
|
|
const handleSaveWithValidation = () => {
|
|
// 프로젝트명 필수
|
|
if (!formData.projectName.trim()) {
|
|
alert('프로젝트(아이템) 명칭이 없습니다.');
|
|
return;
|
|
}
|
|
|
|
// 업무형태가 '휴가'가 아니면 업무내용 필수
|
|
if (formData.type !== '휴가' && !formData.description.trim()) {
|
|
alert('진행 내용이 없습니다.');
|
|
return;
|
|
}
|
|
|
|
// 근무시간 + 초과시간이 0이면 등록 불가
|
|
const totalHours = (formData.hrs || 0) + (formData.ot || 0);
|
|
if (totalHours === 0) {
|
|
alert('근무시간/초과시간이 입력되지 않았습니다.');
|
|
return;
|
|
}
|
|
|
|
// 상태 필수
|
|
if (!formData.status.trim()) {
|
|
alert('상태를 선택하세요.');
|
|
return;
|
|
}
|
|
|
|
// 업무형태 필수
|
|
if (!formData.type.trim()) {
|
|
alert('업무형태를 선택하세요.');
|
|
return;
|
|
}
|
|
|
|
// 공정 필수
|
|
if (!formData.process.trim()) {
|
|
alert('업무프로세스를 선택하세요.');
|
|
return;
|
|
}
|
|
|
|
// 유효성 검사 통과, 저장 진행
|
|
onSave();
|
|
};
|
|
|
|
return createPortal(
|
|
<div
|
|
className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50"
|
|
onMouseDown={onClose}
|
|
>
|
|
<div className="flex items-center justify-center min-h-screen p-4">
|
|
<div
|
|
className="glass-effect rounded-2xl w-full max-w-3xl animate-slide-up max-h-[90vh] overflow-y-auto"
|
|
onMouseDown={(e) => e.stopPropagation()}
|
|
>
|
|
{/* 헤더 */}
|
|
<div className={`px-6 py-4 border-b border-white/10 flex items-center justify-between sticky top-0 backdrop-blur z-10 ${
|
|
editingItem ? 'bg-slate-800/95' : 'bg-primary-600/30'
|
|
}`}>
|
|
<h2 className="text-xl font-semibold text-white flex items-center">
|
|
<FileText className="w-5 h-5 mr-2" />
|
|
{editingItem ? '업무일지 수정' : '업무일지 등록'}
|
|
</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-white/70 hover:text-white transition-colors"
|
|
>
|
|
<X className="w-6 h-6" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* 내용 */}
|
|
<div className="p-6 space-y-4">
|
|
{/* 1행: 날짜, 프로젝트명 */}
|
|
<div className="grid grid-cols-4 gap-4">
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
날짜 *
|
|
</label>
|
|
<input
|
|
type="date"
|
|
value={formData.pdate}
|
|
onChange={(e) => handleFieldChange('pdate', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="col-span-3">
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
프로젝트명 *
|
|
{formData.pidx !== null && formData.pidx > 0 && (
|
|
<span className="ml-2 text-xs text-primary-400 font-mono">[pidx: {formData.pidx}]</span>
|
|
)}
|
|
</label>
|
|
<div className="flex gap-2">
|
|
<input
|
|
type="text"
|
|
value={formData.projectName}
|
|
onChange={(e) => {
|
|
handleFieldChange('projectName', e.target.value);
|
|
// 프로젝트명을 직접 수정하면 pidx 연결 해제
|
|
if (formData.pidx !== null && formData.pidx > 0) {
|
|
onFormChange({ ...formData, projectName: e.target.value, pidx: -1 });
|
|
}
|
|
}}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
setShowProjectSearch(true);
|
|
}
|
|
}}
|
|
className="flex-1 bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
placeholder="프로젝트명 입력 후 Enter로 검색"
|
|
required
|
|
/>
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowProjectSearch(true)}
|
|
className="px-3 py-2 bg-white/20 hover:bg-white/30 border border-white/30 rounded-lg text-white transition-colors"
|
|
title="프로젝트 검색"
|
|
>
|
|
<Search className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 2행: 요청부서, 패키지, 공정 */}
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
요청부서
|
|
</label>
|
|
<select
|
|
value={formData.requestpart}
|
|
onChange={(e) => handleFieldChange('requestpart', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
disabled={loadingCodes}
|
|
>
|
|
<option value="" className="bg-gray-800">선택...</option>
|
|
{requestPartList.map((item) => (
|
|
<option key={item.idx} value={item.memo || item.svalue} className="bg-gray-800">
|
|
{item.memo || item.svalue}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
패키지
|
|
</label>
|
|
<select
|
|
value={formData.package}
|
|
onChange={(e) => handleFieldChange('package', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
disabled={loadingCodes}
|
|
>
|
|
<option value="" className="bg-gray-800">선택...</option>
|
|
{packageList.map((item) => (
|
|
<option key={item.idx} value={item.memo || item.svalue} className="bg-gray-800">
|
|
{item.memo || item.svalue}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
공정 *
|
|
</label>
|
|
<select
|
|
value={formData.process}
|
|
onChange={(e) => handleFieldChange('process', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
disabled={loadingCodes}
|
|
>
|
|
<option value="" className="bg-gray-800">선택...</option>
|
|
{processList.map((item) => (
|
|
<option key={item.idx} value={item.memo || item.svalue} className="bg-gray-800">
|
|
{item.memo || item.svalue}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 3행: 업무형태 선택 버튼 */}
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
업무형태 *
|
|
</label>
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowJobTypeModal(true)}
|
|
className={`w-full border rounded-lg px-4 py-2 text-left flex items-center justify-between focus:outline-none focus:ring-2 focus:ring-primary-400 transition-colors ${formData.type
|
|
? 'bg-white/20 border-white/30 text-white'
|
|
: 'bg-pink-500/30 border-pink-400/50 text-pink-200'
|
|
}`}
|
|
>
|
|
<span>{getJobTypeDisplayText()}</span>
|
|
<ChevronDown className="w-4 h-4 text-white/50" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* 4행: 상태, 근무시간, 초과시간 */}
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
상태 *
|
|
</label>
|
|
<select
|
|
value={formData.status}
|
|
onChange={(e) => handleFieldChange('status', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
disabled={loadingCodes}
|
|
>
|
|
{statusList.length > 0 ? (
|
|
statusList.map((item) => (
|
|
<option key={item.idx} value={item.memo || item.svalue} className="bg-gray-800">
|
|
{item.memo || item.svalue}
|
|
</option>
|
|
))
|
|
) : (
|
|
<>
|
|
<option value="진행 완료" className="bg-gray-800">진행 완료</option>
|
|
<option value="진행 중" className="bg-gray-800">진행 중</option>
|
|
<option value="대기" className="bg-gray-800">대기</option>
|
|
</>
|
|
)}
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
근무시간(h)
|
|
</label>
|
|
<input
|
|
type="number"
|
|
step="0.5"
|
|
min="0"
|
|
max="24"
|
|
value={formData.hrs}
|
|
onChange={(e) =>
|
|
handleFieldChange('hrs', parseFloat(e.target.value) || 0)
|
|
}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
초과시간(h)
|
|
</label>
|
|
<input
|
|
type="number"
|
|
step="0.5"
|
|
min="0"
|
|
max="24"
|
|
value={formData.ot}
|
|
onChange={(e) =>
|
|
handleFieldChange('ot', parseFloat(e.target.value) || 0)
|
|
}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 5행: 초과근무 시간대 (OT > 0일 때만 표시) */}
|
|
{formData.ot > 0 && (
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
초과근무 시작시간
|
|
</label>
|
|
<input
|
|
type="time"
|
|
value={formData.otStart}
|
|
onChange={(e) => handleFieldChange('otStart', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
초과근무 종료시간
|
|
</label>
|
|
<input
|
|
type="time"
|
|
value={formData.otEnd}
|
|
onChange={(e) => handleFieldChange('otEnd', e.target.value)}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* 업무내용 */}
|
|
<div>
|
|
<label className="block text-white/70 text-sm font-medium mb-2">
|
|
업무내용
|
|
</label>
|
|
<textarea
|
|
value={formData.description}
|
|
onChange={(e) => handleFieldChange('description', e.target.value)}
|
|
rows={6}
|
|
className="w-full bg-white/20 border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 resize-none"
|
|
placeholder="업무 내용을 입력하세요"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 푸터 */}
|
|
<div className="px-6 py-4 border-t border-white/10 flex justify-between sticky bottom-0 bg-slate-800/95 backdrop-blur">
|
|
{/* 좌측: 삭제 버튼 (편집 모드일 때만) */}
|
|
<div>
|
|
{editingItem && (
|
|
<button
|
|
onClick={() => {
|
|
if (editingItem) {
|
|
onDelete(editingItem.idx);
|
|
}
|
|
}}
|
|
disabled={processing}
|
|
className="bg-danger-500 hover:bg-danger-600 text-white px-4 py-2 rounded-lg transition-colors flex items-center disabled:opacity-50"
|
|
>
|
|
<Trash2 className="w-4 h-4 mr-2" />
|
|
삭제
|
|
</button>
|
|
)}
|
|
</div>
|
|
{/* 우측: 취소, 저장 버튼 */}
|
|
<div className="flex space-x-3">
|
|
<button
|
|
onClick={onClose}
|
|
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
|
|
>
|
|
취소
|
|
</button>
|
|
<button
|
|
onClick={handleSaveWithValidation}
|
|
disabled={processing}
|
|
className="bg-primary-500 hover:bg-primary-600 text-white px-6 py-2 rounded-lg transition-colors flex items-center disabled:opacity-50"
|
|
>
|
|
{processing ? (
|
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
) : (
|
|
<Plus className="w-4 h-4 mr-2" />
|
|
)}
|
|
{editingItem ? '수정' : '등록'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 업무형태 선택 모달 */}
|
|
<JobTypeSelectModal
|
|
isOpen={showJobTypeModal}
|
|
currentProcess={formData.process}
|
|
currentJobgrp={formData.jobgrp}
|
|
currentType={formData.type}
|
|
onClose={() => setShowJobTypeModal(false)}
|
|
onSelect={handleJobTypeSelect}
|
|
/>
|
|
|
|
{/* 프로젝트 검색 다이얼로그 */}
|
|
<ProjectSearchDialog
|
|
isOpen={showProjectSearch}
|
|
onClose={() => setShowProjectSearch(false)}
|
|
onSelect={async (project) => {
|
|
// 프로젝트가 변경된 경우에만 이전 기록 불러오기
|
|
if (previousProjectIdx !== project.idx) {
|
|
try {
|
|
// 해당 프로젝트의 마지막 업무일지 조회
|
|
const lastReport = await comms.getLastJobReportByProject(project.idx, project.name);
|
|
if (lastReport.Success && lastReport.Data) {
|
|
// 이전 기록의 값들을 기본값으로 설정
|
|
const updatedFormData = {
|
|
...formData,
|
|
projectName: project.name,
|
|
pidx: project.idx > 0 ? project.idx : -1
|
|
};
|
|
|
|
// 이전 기록에서 값 가져오기 (null이 아닌 경우에만)
|
|
if (lastReport.Data.requestpart) {
|
|
updatedFormData.requestpart = lastReport.Data.requestpart;
|
|
}
|
|
if (lastReport.Data.package) {
|
|
updatedFormData.package = lastReport.Data.package;
|
|
}
|
|
if (lastReport.Data.type) {
|
|
updatedFormData.type = lastReport.Data.type;
|
|
}
|
|
if (lastReport.Data.jobgrp) {
|
|
updatedFormData.jobgrp = lastReport.Data.jobgrp;
|
|
}
|
|
if (lastReport.Data.process) {
|
|
updatedFormData.process = lastReport.Data.process;
|
|
}
|
|
if (lastReport.Data.status) {
|
|
updatedFormData.status = lastReport.Data.status;
|
|
}
|
|
|
|
onFormChange(updatedFormData);
|
|
setPreviousProjectIdx(project.idx);
|
|
} else {
|
|
// 이전 기록이 없어도 프로젝트는 설정
|
|
onFormChange({
|
|
...formData,
|
|
projectName: project.name,
|
|
pidx: project.idx > 0 ? project.idx : -1
|
|
});
|
|
setPreviousProjectIdx(project.idx);
|
|
}
|
|
} catch (error) {
|
|
console.error('이전 기록 불러오기 오류:', error);
|
|
// 오류가 나도 프로젝트는 설정
|
|
onFormChange({
|
|
...formData,
|
|
projectName: project.name,
|
|
pidx: project.idx > 0 ? project.idx : -1
|
|
});
|
|
setPreviousProjectIdx(project.idx);
|
|
}
|
|
} else {
|
|
// 동일한 프로젝트면 그냥 설정만
|
|
onFormChange({
|
|
...formData,
|
|
projectName: project.name,
|
|
pidx: project.idx > 0 ? project.idx : -1
|
|
});
|
|
}
|
|
setShowProjectSearch(false);
|
|
}}
|
|
initialSearchKey={formData.projectName}
|
|
/>
|
|
</div>,
|
|
document.body
|
|
);
|
|
}
|