Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/components/production/WorkOrders/WorkOrderCreate.tsx
#	src/components/production/WorkOrders/WorkOrderDetail.tsx
#	src/components/production/WorkOrders/WorkOrderList.tsx
This commit is contained in:
2026-01-12 09:00:32 +09:00
135 changed files with 4955 additions and 1994 deletions

View File

@@ -1,7 +1,7 @@
'use client';
import { Fragment } from 'react';
import { Loader2 } from 'lucide-react';
import { ContentLoadingSpinner } from '@/components/ui/loading-spinner';
import { Checkbox } from '@/components/ui/checkbox';
import {
Table,
@@ -63,10 +63,7 @@ export function ExpenseEstimateForm({ data, onChange, isLoading }: ExpenseEstima
<div className="space-y-6">
<div className="bg-white rounded-lg border p-6">
<h3 className="text-lg font-semibold mb-4"> </h3>
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
<span className="ml-2 text-muted-foreground"> ...</span>
</div>
<ContentLoadingSpinner text="항목을 불러오는 중..." />
</div>
</div>
);

View File

@@ -3,7 +3,9 @@
import { useState, useCallback, useEffect, useTransition, useRef } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { format } from 'date-fns';
import { FileText, Trash2, Send, Save, ArrowLeft, Eye, Loader2 } from 'lucide-react';
import { FileText, Trash2, Send, Save, ArrowLeft, Eye } from 'lucide-react';
import { Loader2 } from 'lucide-react';
import { ContentLoadingSpinner } from '@/components/ui/loading-spinner';
import { toast } from 'sonner';
import {
getExpenseEstimateItems,
@@ -38,6 +40,7 @@ import type {
ExpenseReportData,
ExpenseEstimateData,
} from './types';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
// 초기 데이터 - SSR에서는 빈 문자열, 클라이언트에서 날짜 설정
const getInitialBasicInfo = (): BasicInfo => ({
@@ -137,6 +140,7 @@ export function DocumentCreate() {
router.back();
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('Failed to load document:', error);
toast.error('문서를 불러오는데 실패했습니다.');
router.back();
@@ -186,6 +190,7 @@ export function DocumentCreate() {
router.back();
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('Failed to load document for copy:', error);
toast.error('원본 문서를 불러오는데 실패했습니다.');
router.back();
@@ -211,6 +216,7 @@ export function DocumentCreate() {
});
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('Failed to load expense estimate items:', error);
toast.error('비용견적서 항목을 불러오는데 실패했습니다.');
} finally {
@@ -259,6 +265,7 @@ export function DocumentCreate() {
toast.error(result.error || '문서 삭제에 실패했습니다.');
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('Delete error:', error);
toast.error('문서 삭제 중 오류가 발생했습니다.');
}
@@ -304,6 +311,7 @@ export function DocumentCreate() {
}
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('Submit error:', error);
toast.error('문서 상신 중 오류가 발생했습니다.');
}
@@ -341,6 +349,7 @@ export function DocumentCreate() {
}
}
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('Save draft error:', error);
toast.error('저장 중 오류가 발생했습니다.');
}
@@ -463,9 +472,7 @@ export function DocumentCreate() {
</div>
</CardHeader>
</Card>
<div className="flex items-center justify-center py-20">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
<ContentLoadingSpinner text="문서를 불러오는 중..." />
</div>
);
}