summaryrefslogtreecommitdiff
path: root/components/knox/approval/ApprovalList.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/knox/approval/ApprovalList.tsx')
-rw-r--r--components/knox/approval/ApprovalList.tsx154
1 files changed, 117 insertions, 37 deletions
diff --git a/components/knox/approval/ApprovalList.tsx b/components/knox/approval/ApprovalList.tsx
index 25b9618d..ed26a375 100644
--- a/components/knox/approval/ApprovalList.tsx
+++ b/components/knox/approval/ApprovalList.tsx
@@ -9,7 +9,7 @@ import { toast } from 'sonner';
import { Loader2, List, Eye, RefreshCw, AlertCircle } from 'lucide-react';
// API 함수 및 타입
-import { getSubmissionList, getApprovalHistory } from '@/lib/knox-api/approval/approval';
+import { getSubmissionList, getApprovalHistory, getApprovalLogsAction, syncApprovalStatusAction } from '@/lib/knox-api/approval/approval';
import type { SubmissionListResponse, ApprovalHistoryResponse } from '@/lib/knox-api/approval/approval';
import { formatDate } from '@/lib/utils';
@@ -31,8 +31,13 @@ const getStatusText = (status: string) => {
};
interface ApprovalListProps {
- type?: 'submission' | 'history';
+ type?: 'submission' | 'history' | 'database';
onItemClick?: (apInfId: string) => void;
+ userParams?: {
+ epId?: string;
+ userId?: string;
+ emailAddress?: string;
+ };
}
type ListItem = {
@@ -48,31 +53,51 @@ type ListItem = {
};
export default function ApprovalList({
- type = 'submission',
- onItemClick
+ type = 'database',
+ onItemClick,
+ userParams
}: ApprovalListProps) {
const [listData, setListData] = useState<ListItem[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
+ const [isSyncing, setIsSyncing] = useState(false);
const fetchData = async () => {
setIsLoading(true);
setError(null);
try {
- let response: SubmissionListResponse | ApprovalHistoryResponse;
-
- if (type === 'submission') {
- response = await getSubmissionList();
+ if (type === 'database') {
+ // 새로운 데이터베이스 조회 방식
+ const response = await getApprovalLogsAction();
+
+ if (response.success) {
+ setListData(response.data as unknown as ListItem[]);
+ } else {
+ setError(response.message);
+ toast.error(response.message);
+ }
} else {
- response = await getApprovalHistory();
- }
+ // 기존 Knox API 방식
+ let response: SubmissionListResponse | ApprovalHistoryResponse;
+
+ if (type === 'submission') {
+ if (!userParams || (!userParams.epId && !userParams.userId && !userParams.emailAddress)) {
+ setError('사용자 정보가 필요합니다. (epId, userId, 또는 emailAddress)');
+ toast.error('사용자 정보가 필요합니다.');
+ return;
+ }
+ response = await getSubmissionList(userParams);
+ } else {
+ response = await getApprovalHistory();
+ }
- if (response.result === 'success') {
- setListData(response.data as unknown as ListItem[]);
- } else {
- setError('목록을 가져오는데 실패했습니다.');
- toast.error('목록을 가져오는데 실패했습니다.');
+ if (response.result === 'success') {
+ setListData(response.data as unknown as ListItem[]);
+ } else {
+ setError('목록을 가져오는데 실패했습니다.');
+ toast.error('목록을 가져오는데 실패했습니다.');
+ }
}
} catch (err) {
console.error('목록 조회 오류:', err);
@@ -135,6 +160,32 @@ export default function ApprovalList({
onItemClick?.(apInfId);
};
+ // 결재 상황 동기화 함수
+ const handleSync = async () => {
+ if (type !== 'database') {
+ toast.error('데이터베이스 모드에서만 동기화가 가능합니다.');
+ return;
+ }
+
+ setIsSyncing(true);
+ try {
+ const result = await syncApprovalStatusAction();
+
+ if (result.success) {
+ toast.success(result.message);
+ // 동기화 후 데이터 새로고침
+ await fetchData();
+ } else {
+ toast.error(result.message);
+ }
+ } catch (error) {
+ console.error('동기화 오류:', error);
+ toast.error('동기화 중 오류가 발생했습니다.');
+ } finally {
+ setIsSyncing(false);
+ }
+ };
+
// 컴포넌트 마운트 시 데이터 로드
useEffect(() => {
fetchData();
@@ -145,40 +196,69 @@ export default function ApprovalList({
<CardHeader>
<CardTitle className="flex items-center gap-2">
<List className="w-5 h-5" />
- {type === 'submission' ? '상신함' : '결재 이력'}
+ {type === 'database'
+ ? '결재 로그 (데이터베이스)'
+ : type === 'submission'
+ ? '상신함'
+ : '결재 이력'
+ }
</CardTitle>
<CardDescription>
- {type === 'submission'
- ? '상신한 결재 목록을 확인합니다.'
- : '결재 처리 이력을 확인합니다.'
+ {type === 'database'
+ ? '데이터베이스에 저장된 결재 로그를 확인합니다.'
+ : type === 'submission'
+ ? '상신한 결재 목록을 확인합니다.'
+ : '결재 처리 이력을 확인합니다.'
}
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
- {/* 새로고침 버튼 */}
+ {/* 제어 버튼들 */}
<div className="flex justify-between items-center">
<div className="text-sm text-gray-500">
총 {listData.length}건
</div>
- <Button
- onClick={fetchData}
- disabled={isLoading}
- variant="outline"
- size="sm"
- >
- {isLoading ? (
- <>
- <Loader2 className="w-4 h-4 mr-2 animate-spin" />
- 조회 중...
- </>
- ) : (
- <>
- <RefreshCw className="w-4 h-4 mr-2" />
- 새로고침
- </>
+ <div className="flex gap-2">
+ {type === 'database' && (
+ <Button
+ onClick={handleSync}
+ disabled={isSyncing || isLoading}
+ variant="secondary"
+ size="sm"
+ >
+ {isSyncing ? (
+ <>
+ <Loader2 className="w-4 h-4 mr-2 animate-spin" />
+ 동기화 중...
+ </>
+ ) : (
+ <>
+ <RefreshCw className="w-4 h-4 mr-2" />
+ 상태 동기화
+ </>
+ )}
+ </Button>
)}
- </Button>
+ <Button
+ onClick={fetchData}
+ disabled={isLoading || isSyncing}
+ variant="outline"
+ size="sm"
+ >
+ {isLoading ? (
+ <>
+ <Loader2 className="w-4 h-4 mr-2 animate-spin" />
+ 조회 중...
+ </>
+ ) : (
+ <>
+ <RefreshCw className="w-4 h-4 mr-2" />
+ 새로고침
+ </>
+ )}
+ </Button>
+ </div>
</div>
{/* 에러 메시지 */}