fix(WEB): 폼 컴포넌트 DatePicker 적용 및 코드 정리

- ExpectedExpenseManagement DatePicker 적용 및 간소화
- BoardForm 날짜 필드 개선
- AttendanceInfoDialog, ReasonInfoDialog 코드 정리
- ReceivingDetail 기능 보강
- ShipmentCreate/Edit DatePicker 적용
- VehicleDispatchEdit 수정
- WorkOrderCreate 개선

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-06 16:46:41 +09:00
parent 666eb6bcc6
commit 5344bfc426
9 changed files with 104 additions and 207 deletions

View File

@@ -296,25 +296,25 @@ export function ShipmentCreate() {
return errors.length === 0;
};
const handleSubmit = useCallback(async () => {
if (!validateForm()) return;
const handleSubmit = useCallback(async (): Promise<{ success: boolean; error?: string }> => {
if (!validateForm()) return { success: false, error: '' };
setIsSubmitting(true);
try {
const result = await createShipment(formData);
if (result.success) {
router.push('/ko/outbound/shipments');
} else {
setValidationErrors([result.error || '출고 등록에 실패했습니다.']);
if (!result.success) {
return { success: false, error: result.error || '출고 등록에 실패했습니다.' };
}
return { success: true };
} catch (err) {
if (isNextRedirectError(err)) throw err;
console.error('[ShipmentCreate] handleSubmit error:', err);
setValidationErrors(['저장 중 오류가 발생했습니다.']);
const errorMessage = err instanceof Error ? err.message : '저장 중 오류가 발생했습니다.';
return { success: false, error: errorMessage };
} finally {
setIsSubmitting(false);
}
}, [formData, router]);
}, [formData]);
// 제품 부품 테이블 렌더링
const renderPartsTable = (parts: ProductPart[]) => (
@@ -762,9 +762,8 @@ export function ShipmentCreate() {
mode="create"
isLoading={isLoading}
onCancel={handleCancel}
onSubmit={async (_data: Record<string, unknown>) => {
await handleSubmit();
return { success: true };
onSubmit={async () => {
return await handleSubmit();
}}
renderForm={renderFormContent}
/>

View File

@@ -295,25 +295,25 @@ export function ShipmentEdit({ id }: ShipmentEditProps) {
return errors.length === 0;
};
const handleSubmit = useCallback(async () => {
if (!validateForm()) return;
const handleSubmit = useCallback(async (): Promise<{ success: boolean; error?: string }> => {
if (!validateForm()) return { success: false, error: '' };
setIsSubmitting(true);
try {
const result = await updateShipment(id, formData);
if (result.success) {
router.push(`/ko/outbound/shipments/${id}?mode=view`);
} else {
setValidationErrors([result.error || '출고 수정에 실패했습니다.']);
if (!result.success) {
return { success: false, error: result.error || '출고 수정에 실패했습니다.' };
}
return { success: true };
} catch (err) {
if (isNextRedirectError(err)) throw err;
console.error('[ShipmentEdit] handleSubmit error:', err);
setValidationErrors(['저장 중 오류가 발생했습니다.']);
const errorMessage = err instanceof Error ? err.message : '저장 중 오류가 발생했습니다.';
return { success: false, error: errorMessage };
} finally {
setIsSubmitting(false);
}
}, [id, formData, router]);
}, [id, formData]);
// 제품 부품 테이블 렌더링
const renderPartsTable = (parts: ProductPart[]) => (
@@ -781,9 +781,8 @@ export function ShipmentEdit({ id }: ShipmentEditProps) {
mode="edit"
isLoading={isLoading}
onCancel={handleCancel}
onSubmit={async (_data: Record<string, unknown>) => {
await handleSubmit();
return { success: true };
onSubmit={async () => {
return await handleSubmit();
}}
renderForm={renderFormContent}
/>

View File

@@ -21,6 +21,7 @@ import {
} from '@/components/ui/select';
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
import { vehicleDispatchEditConfig } from './vehicleDispatchConfig';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { getVehicleDispatchById, updateVehicleDispatch } from './actions';
import {
VEHICLE_DISPATCH_STATUS_LABELS,
@@ -135,22 +136,23 @@ export function VehicleDispatchEdit({ id }: VehicleDispatchEditProps) {
router.push(`/ko/outbound/vehicle-dispatches/${id}?mode=view`);
}, [router, id]);
const handleSubmit = useCallback(async () => {
const handleSubmit = useCallback(async (): Promise<{ success: boolean; error?: string }> => {
setIsSubmitting(true);
try {
const result = await updateVehicleDispatch(id, formData);
if (result.success) {
router.push(`/ko/outbound/vehicle-dispatches/${id}?mode=view`);
} else {
setValidationErrors([result.error || '배차차량 수정에 실패했습니다.']);
if (!result.success) {
return { success: false, error: result.error || '배차차량 수정에 실패했습니다.' };
}
return { success: true };
} catch (err) {
if (isNextRedirectError(err)) throw err;
console.error('[VehicleDispatchEdit] handleSubmit error:', err);
setValidationErrors(['저장 중 오류가 발생했습니다.']);
const errorMessage = err instanceof Error ? err.message : '저장 중 오류가 발생했습니다.';
return { success: false, error: errorMessage };
} finally {
setIsSubmitting(false);
}
}, [id, formData, router]);
}, [id, formData]);
// 동적 config
const dynamicConfig = {
@@ -387,9 +389,8 @@ export function VehicleDispatchEdit({ id }: VehicleDispatchEditProps) {
mode="edit"
isLoading={isLoading}
onCancel={handleCancel}
onSubmit={async (_data: Record<string, unknown>) => {
await handleSubmit();
return { success: true };
onSubmit={async () => {
return await handleSubmit();
}}
renderForm={renderFormContent}
/>