// components/sync/send-to-shi-button.tsx (최종 버전) "use client" import * as React from "react" import { Send, Loader2, CheckCircle, AlertTriangle, Settings } from "lucide-react" import { toast } from "sonner" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" import { Badge } from "@/components/ui/badge" import { Progress } from "@/components/ui/progress" import { Separator } from "@/components/ui/separator" import { useSyncStatus, useTriggerSync } from "@/hooks/use-sync-status" import type { EnhancedDocument } from "@/types/enhanced-documents" interface SendToSHIButtonProps { contractId: number documents?: EnhancedDocument[] onSyncComplete?: () => void } export function SendToSHIButton({ contractId, documents = [], onSyncComplete }: SendToSHIButtonProps) { const [isDialogOpen, setIsDialogOpen] = React.useState(false) const [syncProgress, setSyncProgress] = React.useState(0) const { syncStatus, isLoading: statusLoading, error: statusError, refetch: refetchStatus } = useSyncStatus(contractId, 'SHI') const { triggerSync, isLoading: isSyncing, error: syncError } = useTriggerSync() // 에러 상태 표시 React.useEffect(() => { if (statusError) { console.warn('Failed to load sync status:', statusError) } }, [statusError]) const handleSync = async () => { if (!contractId) return setSyncProgress(0) try { // 진행률 시뮬레이션 const progressInterval = setInterval(() => { setSyncProgress(prev => Math.min(prev + 10, 90)) }, 200) const result = await triggerSync({ contractId, targetSystem: 'SHI' }) clearInterval(progressInterval) setSyncProgress(100) setTimeout(() => { setSyncProgress(0) setIsDialogOpen(false) if (result?.success) { toast.success( `동기화 완료: ${result.successCount || 0}건 성공`, { description: result.successCount > 0 ? `${result.successCount}개 항목이 SHI 시스템으로 전송되었습니다.` : '전송할 새로운 변경사항이 없습니다.' } ) } else { toast.error( `동기화 부분 실패: ${result?.successCount || 0}건 성공, ${result?.failureCount || 0}건 실패`, { description: result?.errors?.[0] || '일부 항목 전송에 실패했습니다.' } ) } refetchStatus() // SWR 캐시 갱신 onSyncComplete?.() }, 500) } catch (error) { setSyncProgress(0) toast.error('동기화 실패', { description: error instanceof Error ? error.message : '알 수 없는 오류가 발생했습니다.' }) } } const getSyncStatusBadge = () => { if (statusLoading) { return 확인 중... } if (statusError) { return 오류 } if (!syncStatus) { return 데이터 없음 } if (syncStatus.pendingChanges > 0) { return ( {syncStatus.pendingChanges}건 대기 ) } if (syncStatus.syncedChanges > 0) { return ( 동기화됨 ) } return 변경사항 없음 } const canSync = !statusError && syncStatus?.syncEnabled && syncStatus?.pendingChanges > 0 return ( <>

SHI 동기화 상태

현재 상태 {getSyncStatusBadge()}
{syncStatus && !statusError && (
대기 중
{syncStatus.pendingChanges || 0}건
동기화됨
{syncStatus.syncedChanges || 0}건
{syncStatus.failedChanges > 0 && (
실패
{syncStatus.failedChanges}건
)} {syncStatus.lastSyncAt && (
마지막 동기화
{new Date(syncStatus.lastSyncAt).toLocaleString()}
)}
)} {statusError && (
연결 오류
동기화 상태를 확인할 수 없습니다.
)}
{/* 동기화 진행 다이얼로그 */} SHI 시스템으로 동기화 변경된 문서 데이터를 SHI 시스템으로 전송합니다.
{syncStatus && !statusError && (
전송 대상 {syncStatus.pendingChanges || 0}건
문서, 리비전, 첨부파일의 변경사항이 포함됩니다.
{isSyncing && (
진행률 {syncProgress}%
)}
)} {statusError && (
동기화 상태를 확인할 수 없습니다. 네트워크 연결을 확인해주세요.
)}
) }