summaryrefslogtreecommitdiff
path: root/components/polices/policy-preview.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-08-06 04:23:40 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-08-06 04:23:40 +0000
commitde2ac5a2860bc25180971e7a11f852d9d44675b7 (patch)
treeb931c363f2cb19e177a0a7b17190d5de2a82d709 /components/polices/policy-preview.tsx
parent6c549b0f264e9be4d60af38f9efc05b189d6849f (diff)
(대표님) 정기평가, 법적검토, 정책, 가입관련 처리 및 관련 컴포넌트 추가, 메뉴 변경
Diffstat (limited to 'components/polices/policy-preview.tsx')
-rw-r--r--components/polices/policy-preview.tsx191
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