fix: [작업자화면] 작업정보 저장 로직 전면 재구성

- saveWorkOrderField 헬퍼: API 저장 + workOrders state 동시 동기화
- 부서/담당자/생산일자 onChange → saveWorkOrderField로 통일
- workOrders state 동기화로 다른 작업지시 선택 후 돌아와도 값 유지
- useEffect: selectedSidebarOrderId 변경 시에만 workOrders state에서 로드
- 단계 완료/검사 완료/자동 완료 시 생산일자도 saveWorkOrderField 사용
This commit is contained in:
김보곤
2026-03-22 18:50:15 +09:00
parent db3ebc3f82
commit 2ca4dbb821

View File

@@ -178,6 +178,22 @@ export default function WorkerScreen() {
const [departmentList, setDepartmentList] = useState<DepartmentOption[]>([]);
const [departmentUsers, setDepartmentUsers] = useState<DepartmentUser[]>([]);
// 작업정보 변경 → API 저장 + workOrders state 동기화
const saveWorkOrderField = useCallback((field: 'scheduled_date' | 'team_id' | 'assignee_id', value: string | number | null) => {
const orderId = selectedSidebarOrderId;
if (!orderId) return;
// API 저장
updateWorkOrderInfo(orderId, { [field]: value });
// workOrders state 동기화 (다른 작업지시 선택 후 돌아와도 값 유지)
setWorkOrders(prev => prev.map(wo => {
if (wo.id !== orderId) return wo;
if (field === 'scheduled_date') return { ...wo, scheduledDate: value as string };
if (field === 'team_id') return { ...wo, teamId: value as number };
if (field === 'assignee_id') return { ...wo, assigneeId: value as number };
return wo;
}));
}, [selectedSidebarOrderId]);
// 좌측 사이드바
const [selectedSidebarOrderId, setSelectedSidebarOrderId] = useState<string>('');
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
@@ -863,33 +879,31 @@ export default function WorkerScreen() {
}, [selectedSidebarOrderId, workItems.length]);
// ===== 작업지시 변경 시 작업 정보 자동 세팅 (선택 변경 시에만) =====
const prevSidebarOrderIdRef = useRef<string | null>(null);
// ===== 작업지시 변경 시 작업 정보 자동 세팅 =====
// selectedSidebarOrderId 변경 시 workOrders state에서 저장된 값을 로드
useEffect(() => {
// 같은 작업지시를 다시 선택한 경우 덮어쓰지 않음 (사용자 수정값 보존)
if (prevSidebarOrderIdRef.current === selectedSidebarOrderId) return;
prevSidebarOrderIdRef.current = selectedSidebarOrderId;
const apiOrder = filteredWorkOrders.find((wo) => wo.id === selectedSidebarOrderId);
if (apiOrder) {
// 부서 세팅: 1순위 work_orders.team_id → 2순위 process.department(부서명 매칭)
if (apiOrder.teamId) {
setDepartmentId(String(apiOrder.teamId));
} else if (apiOrder.processDepartment && departmentList.length > 0) {
const matched = departmentList.find((d) => d.name === apiOrder.processDepartment);
setDepartmentId(matched ? String(matched.id) : '');
} else {
setDepartmentId('');
}
// 생산담당자 세팅
setProductionManagerId(apiOrder.assigneeId ? String(apiOrder.assigneeId) : '');
// 생산일자 세팅
setProductionDate(apiOrder.scheduledDate || '');
} else {
if (!selectedSidebarOrderId) {
setDepartmentId('');
setProductionManagerId('');
setProductionDate('');
return;
}
const apiOrder = workOrders.find((wo) => wo.id === selectedSidebarOrderId);
if (!apiOrder) return;
// 부서 세팅: 1순위 work_orders.team_id → 2순위 process.department(부서명 매칭)
if (apiOrder.teamId) {
setDepartmentId(String(apiOrder.teamId));
} else if (apiOrder.processDepartment && departmentList.length > 0) {
const matched = departmentList.find((d) => d.name === apiOrder.processDepartment);
setDepartmentId(matched ? String(matched.id) : '');
} else {
setDepartmentId('');
}
// 생산담당자 세팅
setProductionManagerId(apiOrder.assigneeId ? String(apiOrder.assigneeId) : '');
// 생산일자 세팅
setProductionDate(apiOrder.scheduledDate || '');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedSidebarOrderId]);
@@ -1048,15 +1062,15 @@ export default function WorkerScreen() {
if (result.data.is_completed && !productionDate) {
const today = new Date().toISOString().slice(0, 10);
setProductionDate(today);
updateWorkOrderInfo(orderId, { scheduled_date: today });
saveWorkOrderField('scheduled_date', today);
}
// 모든 단계 완료 시 작업지시 자동 완료 → 생산일자 저장 + 목록 새로고침
if (result.data.work_order_status_changed) {
toast.success('모든 공정 단계 완료 — 작업지시가 자동 완료되었습니다.');
const today = new Date().toISOString().slice(0, 10);
await updateWorkOrderInfo(orderId, { scheduled_date: today });
setProductionDate(today);
saveWorkOrderField('scheduled_date', today);
try {
const refreshResult = await getMyWorkOrders();
if (refreshResult.success) setWorkOrders(refreshResult.data);
@@ -1384,10 +1398,10 @@ export default function WorkerScreen() {
setStepCompletionMap((prev) => ({ ...prev, [buildStepKey(stepName)]: true }));
}
// 4. 생산일자 자동 저장 (검사 완료 시점 = 생산일자)
if (selectedOrder) {
{
const today = new Date().toISOString().slice(0, 10);
await updateWorkOrderInfo(selectedOrder.id, { scheduled_date: today });
setProductionDate(today);
saveWorkOrderField('scheduled_date', today);
}
// 5. 작업 목록 리프레시 (상태 변경 반영 → 사이드바 대기/완료 탭 갱신)
@@ -1596,9 +1610,7 @@ export default function WorkerScreen() {
value={departmentId}
onValueChange={(v) => {
setDepartmentId(v);
if (selectedOrder && v) {
updateWorkOrderInfo(selectedOrder.id, { team_id: Number(v) });
}
if (v) saveWorkOrderField('team_id', Number(v));
}}
>
<SelectTrigger>
@@ -1620,9 +1632,7 @@ export default function WorkerScreen() {
value={productionManagerId}
onValueChange={(v) => {
setProductionManagerId(v);
if (selectedOrder && v) {
updateWorkOrderInfo(selectedOrder.id, { assignee_id: Number(v) });
}
if (v) saveWorkOrderField('assignee_id', Number(v));
}}
disabled={!departmentId}
>
@@ -1644,9 +1654,7 @@ export default function WorkerScreen() {
value={productionDate}
onChange={(date) => {
setProductionDate(date);
if (selectedOrder && date) {
updateWorkOrderInfo(selectedOrder.id, { scheduled_date: date });
}
if (date) saveWorkOrderField('scheduled_date', date);
}}
/>
</div>