'use client' import { useState, useTransition } from 'react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Badge } from '@/components/ui/badge' import { Separator } from '@/components/ui/separator' import { Alert, AlertDescription } from '@/components/ui/alert' import { Plus, Edit, Eye, History, Save, X, Shield, FileText, Calendar, Clock, CheckCircle2, AlertCircle, Loader2 } from 'lucide-react' import { PolicyEditor } from './policy-editor' import { PolicyPreview } from './policy-preview' import { PolicyHistory } from './policy-history' import { useToast } from "@/hooks/use-toast"; import { activatePolicyVersion, createPolicyVersion, getPolicyHistory } from '@/lib/polices/service' import { useRouter } from "next/navigation" interface PolicyManagementClientProps { initialData: { currentPolicies: Record allPolicies: Record stats: any } currentLocale?: 'ko' | 'en' } export function PolicyManagementClient({ initialData, currentLocale = 'ko' }: PolicyManagementClientProps) { const [currentTab, setCurrentTab] = useState('privacy_policy') const [editingPolicy, setEditingPolicy] = useState(null) const [viewingHistory, setViewingHistory] = useState(null) const [previewData, setPreviewData] = useState(null) // ✅ 초기 데이터를 안전하게 설정 const [policies, setPolicies] = useState(() => { const safePolicies = { ...initialData.allPolicies } // 각 정책 타입에 대해 빈 배열로 초기화 if (!safePolicies.privacy_policy) safePolicies.privacy_policy = [] if (!safePolicies.terms_of_service) safePolicies.terms_of_service = [] return safePolicies }) const [currentPolicies, setCurrentPolicies] = useState(initialData.currentPolicies || {}) const [isPending, startTransition] = useTransition() const { toast } = useToast(); const router = useRouter() const policyTypes = [ { key: 'privacy_policy', label: '개인정보 처리방침', icon: , description: '개인정보 수집, 이용, 보관 및 파기에 관한 정책' }, { key: 'terms_of_service', label: '이용약관', icon: , description: '서비스 이용 시 준수해야 할 규칙과 조건' } ] const handleCreateNew = (policyType: string) => { setEditingPolicy(policyType) setViewingHistory(null) setPreviewData(null) } const handleEdit = (policyType: string) => { setEditingPolicy(policyType) setViewingHistory(null) setPreviewData(null) } const handleViewHistory = async (policyType: string) => { setViewingHistory(policyType) setEditingPolicy(null) setPreviewData(null) startTransition(async () => { try { const result = await getPolicyHistory(policyType, currentLocale) if (result.success) { setPolicies(prev => ({ ...prev, [policyType]: result.data || [] })) } } catch (error) { console.error('Policy history error:', error) toast({ variant: "destructive", title: "오류", description: "정책 히스토리를 불러오는데 실패했습니다.", }) } }) } const handlePreview = (policyType: string, content: string, version: string) => { setPreviewData({ policyType, content, version, effectiveDate: new Date().toISOString() }) setEditingPolicy(null) setViewingHistory(null) } const handleSavePolicy = async (policyType: string, version: string, content: string) => { if (!content.trim()) { toast({ variant: "destructive", title: "오류", description: "정책 내용을 입력해주세요.", }) return } startTransition(async () => { try { console.log('Saving policy:', { policyType, version }) // ✅ 디버깅 로그 const result = await createPolicyVersion({ policyType: policyType as 'privacy_policy' | 'terms_of_service', locale: currentLocale, version, content, effectiveDate: new Date() }) console.log('Save result:', result) // ✅ 디버깅 로그 if (result.success) { toast({ title: "성공", description: "새 정책 버전이 생성되었습니다.", }) // ✅ 상태 업데이트 - 안전하게 처리 const newPolicy = result.policy setPolicies(prev => { console.log('Updating policies state:', { prev, policyType, newPolicy }) // 디버깅 로그 return { ...prev, [policyType]: [newPolicy, ...(prev[policyType] || [])] // ✅ 안전한 스프레드 } }) setCurrentPolicies(prev => { console.log('Updating current policies state:', { prev, policyType, newPolicy }) // 디버깅 로그 return { ...prev, [policyType]: newPolicy } }) setEditingPolicy(null) // ✅ Router refresh를 상태 업데이트 후에 호출 router.refresh() } else { throw new Error(result.error) } } catch (error) { console.error('Save policy error:', error) // ✅ 에러 로그 toast({ variant: "destructive", title: "오류", description: error?.message || "정책 저장에 실패했습니다.", }) } }) } const handleActivatePolicy = async (policyId: number, policyType: string) => { startTransition(async () => { try { const result = await activatePolicyVersion(policyId) if (result.success) { toast({ title: "성공", description: "정책이 활성화되었습니다.", }) // ✅ 현재 정책 업데이트 - 안전하게 처리 const activatedPolicy = (policies[policyType] || []).find(p => p.id === policyId) if (activatedPolicy) { setCurrentPolicies(prev => ({ ...prev, [policyType]: activatedPolicy })) // ✅ 정책 목록의 isCurrent 상태 업데이트 setPolicies(prev => ({ ...prev, [policyType]: (prev[policyType] || []).map(p => ({ ...p, isCurrent: p.id === policyId })) })) } router.refresh() } else { throw new Error(result.error) } } catch (error) { console.error('Activate policy error:', error) toast({ variant: "destructive", title: "오류", description: error?.message || "정책 활성화에 실패했습니다.", }) } }) } const renderMainContent = () => { const currentPolicy = currentPolicies[currentTab] const policyInfo = policyTypes.find(p => p.key === currentTab) // ✅ 디버깅 정보 console.log('Render main content:', { currentTab, currentPolicy, editingPolicy, policiesForTab: policies[currentTab]?.length || 0 }) if (editingPolicy === currentTab) { return ( setEditingPolicy(null)} onPreview={handlePreview} isLoading={isPending} currentLocale={currentLocale} /> ) } if (viewingHistory === currentTab) { return ( setEditingPolicy(currentTab)} onClose={() => setViewingHistory(null)} isLoading={isPending} /> ) } if (previewData && previewData.policyType === currentTab) { return ( handleSavePolicy(previewData.policyType, previewData.version, previewData.content)} onEdit={() => setEditingPolicy(currentTab)} onClose={() => setPreviewData(null)} isLoading={isPending} /> ) } // 기본 정책 관리 화면 return (
{policyInfo?.icon} {policyInfo?.label} {policyInfo?.description}
{currentPolicy && ( <> )}
{currentPolicy ? (
{/* 현재 정책 정보 */}

현재 활성 버전: v{currentPolicy.version}

시행일: {new Date(currentPolicy.effectiveDate).toLocaleDateString('ko-KR')}

활성
{/* 정책 내용 미리보기 */}

정책 내용 미리보기

1000 ? '...' : '') }} />
{/* 메타 정보 */}
생성일: {new Date(currentPolicy.createdAt).toLocaleString('ko-KR')}
버전: {currentPolicy.version}
) : (

정책이 등록되지 않았습니다

{policyInfo?.label}의 첫 번째 버전을 생성해주세요.

)} ) } return (

정책 편집

{isPending && (
처리 중...
)}
{policyTypes.map(policy => ( {policy.icon} {policy.label} ))} {policyTypes.map(policy => ( {renderMainContent()} ))}
) }