diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-06 04:23:40 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-06 04:23:40 +0000 |
| commit | de2ac5a2860bc25180971e7a11f852d9d44675b7 (patch) | |
| tree | b931c363f2cb19e177a0a7b17190d5de2a82d709 /components/polices/policy-preview.tsx | |
| parent | 6c549b0f264e9be4d60af38f9efc05b189d6849f (diff) | |
(대표님) 정기평가, 법적검토, 정책, 가입관련 처리 및 관련 컴포넌트 추가, 메뉴 변경
Diffstat (limited to 'components/polices/policy-preview.tsx')
| -rw-r--r-- | components/polices/policy-preview.tsx | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/components/polices/policy-preview.tsx b/components/polices/policy-preview.tsx new file mode 100644 index 00000000..059b2d72 --- /dev/null +++ b/components/polices/policy-preview.tsx @@ -0,0 +1,191 @@ +import { useState, useEffect } from 'react' +import { Button } from '@/components/ui/button' +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' +import { Separator } from '@/components/ui/separator' +import { Save, Eye, X, Info, AlertTriangle, Calendar, Clock, FileText, Shield } from 'lucide-react' +import { Badge } from '../ui/badge' + +// ✅ 타입 정의 +interface PolicyPreviewData { + policyType: 'privacy_policy' | 'terms_of_service' + content: string + version: string + effectiveDate: string + id?: number + isCurrent?: boolean + createdAt?: string +} + +interface PolicyPreviewProps { + data: PolicyPreviewData + onSave?: () => void + onEdit?: () => void + onClose: () => void + isLoading?: boolean + mode?: 'preview' | 'view' // ✅ 미리보기 모드 vs 상세보기 모드 +} + +export function PolicyPreview({ + data, + onSave, + onEdit, + onClose, + isLoading = false, + mode = 'preview' +}: PolicyPreviewProps) { + const policyLabels: Record<string, string> = { + privacy_policy: '개인정보 처리방침', + terms_of_service: '이용약관' + } + + const policyIcons = { + privacy_policy: <Shield className="h-5 w-5" />, + terms_of_service: <FileText className="h-5 w-5" /> + } + + // ✅ 모드에 따른 제목과 설명 + const getTitle = () => { + return mode === 'preview' ? '정책 미리보기' : '정책 상세보기' + } + + const getDescription = () => { + if (mode === 'preview') { + return `${policyLabels[data.policyType]} v${data.version} - 저장하면 즉시 활성화됩니다` + } else { + return `${policyLabels[data.policyType]} v${data.version} 상세 내용` + } + } + + // ✅ 상태 텍스트 결정 + const getStatusText = () => { + if (mode === 'preview') return '저장 대기' + if (data.isCurrent) return '현재 활성' + return '비활성' + } + + const getStatusBadge = () => { + if (mode === 'preview') { + return <Badge variant="outline" className="text-orange-600">저장 대기</Badge> + } + if (data.isCurrent) { + return <Badge className="bg-green-100 text-green-800">현재 활성</Badge> + } + return <Badge variant="secondary">비활성</Badge> + } + + return ( + <Card> + <CardHeader> + <div className="flex items-center justify-between"> + <div className="flex items-center gap-3"> + {policyIcons[data.policyType]} + <div> + <CardTitle>{getTitle()}</CardTitle> + <CardDescription> + {getDescription()} + </CardDescription> + </div> + </div> + <Button variant="outline" size="sm" onClick={onClose}> + <X className="h-4 w-4" /> + </Button> + </div> + </CardHeader> + <CardContent className="space-y-6"> + {/* ✅ 정책 메타 정보 */} + <div className="grid grid-cols-2 gap-4 p-4 bg-muted/50 rounded-lg"> + <div> + <p className="text-sm font-medium">정책 유형</p> + <p className="text-sm text-muted-foreground">{policyLabels[data.policyType]}</p> + </div> + <div> + <p className="text-sm font-medium">버전</p> + <p className="text-sm text-muted-foreground">v{data.version}</p> + </div> + <div> + <p className="text-sm font-medium">시행일</p> + <p className="text-sm text-muted-foreground"> + {new Date(data.effectiveDate).toLocaleDateString('ko-KR')} + </p> + </div> + <div> + <p className="text-sm font-medium">상태</p> + <div className="flex items-center gap-2"> + {getStatusBadge()} + </div> + </div> + + {/* ✅ 상세보기 모드일 때 추가 정보 */} + {mode === 'view' && data.createdAt && ( + <> + <div> + <p className="text-sm font-medium">생성일</p> + <p className="text-sm text-muted-foreground"> + {new Date(data.createdAt).toLocaleString('ko-KR')} + </p> + </div> + <div> + <p className="text-sm font-medium">문서 ID</p> + <p className="text-sm text-muted-foreground">#{data.id}</p> + </div> + </> + )} + </div> + + <Separator /> + + {/* ✅ 정책 내용 미리보기 */} + <div className="space-y-2"> + <div className="flex items-center justify-between"> + <h4 className="font-medium">정책 내용</h4> + <div className="text-xs text-muted-foreground"> + {data.content.replace(/<[^>]*>/g, '').length}자 + </div> + </div> + <div className="bg-white border rounded-md p-6 max-h-96 overflow-y-auto"> + <div + className="prose prose-sm max-w-none" + dangerouslySetInnerHTML={{ __html: data.content }} + /> + </div> + </div> + + {/* ✅ 액션 버튼들 */} + <div className="flex justify-between pt-4"> + {mode === 'preview' ? ( + // 미리보기 모드 버튼들 + <> + <Button + variant="outline" + onClick={onEdit} + disabled={isLoading} + > + 편집으로 돌아가기 + </Button> + + <Button + onClick={onSave} + disabled={isLoading} + className="bg-green-600 hover:bg-green-700" + > + <Save className="h-4 w-4 mr-2" /> + {isLoading ? '저장 중...' : '저장 및 활성화'} + </Button> + </> + ) : ( + // 상세보기 모드 버튼들 + <div className="w-full flex justify-end"> + <Button + variant="outline" + onClick={onClose} + disabled={isLoading} + > + 닫기 + </Button> + </div> + )} + </div> + </CardContent> + </Card> + ) +}
\ No newline at end of file |
