diff options
Diffstat (limited to 'components/signup/conset-step.tsx')
| -rw-r--r-- | components/signup/conset-step.tsx | 79 |
1 files changed, 49 insertions, 30 deletions
diff --git a/components/signup/conset-step.tsx b/components/signup/conset-step.tsx index 3260a7b7..4d0a544f 100644 --- a/components/signup/conset-step.tsx +++ b/components/signup/conset-step.tsx @@ -5,6 +5,7 @@ import { Separator } from '@/components/ui/separator'; import { ChevronDown, ChevronUp, FileText, Shield, Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; import { getCurrentPolicies } from '@/lib/polices/service'; +import { useTranslation } from '@/i18n/client'; // ✅ 정책 데이터 타입 개선 interface PolicyData { @@ -30,9 +31,12 @@ interface ConsentStepProps { }; onChange: (updater: (prev: any) => any) => void; onNext: () => void; + lng: string; // 언어 코드 추가 } -export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps) { +export default function ConsentStep({ data, onChange, onNext, lng }: ConsentStepProps) { + const { t } = useTranslation(lng, 'consent'); + const [policyData, setPolicyData] = useState<PolicyVersions | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); @@ -58,11 +62,11 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps console.log('Policy data loaded:', result.data); setPolicyData(result.data); } else { - setError(result.error || '정책 데이터를 불러올 수 없습니다.'); + setError(result.error || t('policyLoadError')); console.error('Failed to fetch policy data:', result.error); } } catch (error) { - const errorMessage = '정책 데이터를 불러오는 중 오류가 발생했습니다.'; + const errorMessage = t('policyFetchError'); setError(errorMessage); console.error('Failed to fetch policy data:', error); } finally { @@ -100,7 +104,7 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps // ✅ 정책 미리보기 텍스트 생성 const renderPolicyPreview = (policy: PolicyData, maxLength = 200): string => { - if (!policy?.content) return '내용 없음'; + if (!policy?.content) return t('noContent'); const textContent = stripHtmlTags(policy.content); return textContent.length > maxLength @@ -114,7 +118,7 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps <div className="flex items-center justify-center p-8"> <div className="flex items-center gap-2 text-gray-600"> <Loader2 className="h-4 w-4 animate-spin" /> - 정책 내용을 불러오는 중... + {t('loadingPolicies')} </div> </div> ); @@ -125,10 +129,10 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps return ( <div className="text-center p-8"> <div className="text-red-600 mb-4"> - {error || '정책 내용을 불러올 수 없습니다.'} + {error || t('policyLoadError')} </div> <Button onClick={fetchPolicyData} variant="outline"> - 다시 시도 + {t('retryButton')} </Button> </div> ); @@ -139,11 +143,11 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps return ( <div className="text-center p-8"> <div className="text-amber-600 mb-4"> - 일부 정책이 설정되지 않았습니다. 관리자에게 문의해주세요. + {t('policiesNotConfigured')} </div> <div className="text-sm text-gray-500"> - {!policyData.privacy_policy && '개인정보 처리방침이 없습니다.'}<br /> - {!policyData.terms_of_service && '이용약관이 없습니다.'} + {!policyData.privacy_policy && t('missingPrivacyPolicy')}<br /> + {!policyData.terms_of_service && t('missingTermsOfService')} </div> </div> ); @@ -152,9 +156,9 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps return ( <div className="space-y-6"> <div> - <h2 className="text-xl font-semibold mb-2">서비스 이용 약관 동의</h2> + <h2 className="text-xl font-semibold mb-2">{t('consentTitle')}</h2> <p className="text-gray-600 text-sm"> - 서비스 이용을 위해 다음 약관에 동의해주세요. 각 항목을 클릭하여 상세 내용을 확인할 수 있습니다. + {t('consentDescription')} </p> </div> @@ -169,11 +173,13 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps policy={policyData.privacy_policy} isRequired={true} icon={<Shield className="w-4 h-4" />} - title="개인정보 처리방침" - description="개인정보 수집, 이용, 보관 및 파기에 관한 정책입니다." + title={t('privacyPolicyTitle')} + description={t('privacyPolicyDescription')} expanded={expandedSections.privacy} onToggleExpand={() => toggleSection('privacy')} onShowModal={() => setShowPrivacyModal(true)} + t={t} + lng={lng} /> )} @@ -189,15 +195,16 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps policy={policyData.terms_of_service} isRequired={true} icon={<FileText className="w-4 h-4" />} - title="이용약관" - description="서비스 이용 시 준수해야 할 규칙과 조건입니다." + title={t('termsOfServiceTitle')} + description={t('termsOfServiceDescription')} expanded={expandedSections.terms} onToggleExpand={() => toggleSection('terms')} onShowModal={() => setShowTermsModal(true)} + t={t} + lng={lng} /> )} - {/* ✅ 전체 동의 */} <div className="pt-4 border-t bg-gray-50 p-4 rounded-lg"> <div className="flex items-center space-x-3"> @@ -216,7 +223,7 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps className="h-5 w-5 text-blue-600 border-gray-300 rounded focus:ring-blue-500" /> <label htmlFor="all-consent" className="text-base font-medium cursor-pointer"> - 위 내용에 모두 동의합니다 + {t('agreeToAll')} </label> </div> </div> @@ -224,7 +231,7 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps <div className="flex justify-end"> <Button onClick={onNext} disabled={!isValid} size="lg"> - 다음 단계로 + {t('nextStep')} </Button> </div> @@ -237,6 +244,8 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps onChange(prev => ({ ...prev, privacy: true })); setShowPrivacyModal(false); }} + t={t} + lng={lng} /> )} @@ -249,6 +258,8 @@ export default function ConsentStep({ data, onChange, onNext }: ConsentStepProps onChange(prev => ({ ...prev, terms: true })); setShowTermsModal(false); }} + t={t} + lng={lng} /> )} </div> @@ -269,15 +280,17 @@ interface PolicyConsentSectionProps { expanded: boolean; onToggleExpand: () => void; onShowModal: () => void; + t: (key: string, options?: any) => string; + lng: string; } function PolicyConsentSection({ id, type, checked, onChange, policy, isRequired, icon, title, description, - expanded, onToggleExpand, onShowModal + expanded, onToggleExpand, onShowModal, t, lng }: PolicyConsentSectionProps) { // ✅ HTML에서 텍스트 추출 const renderPolicyPreview = (content: string, maxLength = 300): string => { - if (!content) return '내용 없음'; + if (!content) return t('noContent'); const textContent = content .replace(/<[^>]*>/g, '') // HTML 태그 제거 @@ -311,7 +324,7 @@ function PolicyConsentSection({ {icon} <label htmlFor={id} className="text-sm font-medium cursor-pointer"> <span className={isRequired ? "text-red-500" : "text-blue-500"}> - [{isRequired ? "필수" : "선택"}] + [{isRequired ? t('required') : t('optional')}] </span> {title} (v{policy.version}) </label> </div> @@ -331,7 +344,7 @@ function PolicyConsentSection({ className="flex items-center space-x-1 text-blue-600 hover:underline" > {expanded ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />} - <span>{expanded ? '간략히' : '더보기'}</span> + <span>{expanded ? t('showLess') : t('showMore')}</span> </button> <span className="text-gray-400">|</span> <button @@ -339,11 +352,13 @@ function PolicyConsentSection({ onClick={onShowModal} className="text-blue-600 hover:underline" > - 전문보기 + {t('viewFullText')} </button> <span className="text-gray-400">|</span> <span className="text-gray-500"> - 시행일: {new Date(policy.effectiveDate).toLocaleDateString('ko-KR')} + {t('effectiveDate')}: {new Date(policy.effectiveDate).toLocaleDateString( + lng === 'ko' ? 'ko-KR' : 'en-US' + )} </span> </div> </div> @@ -357,11 +372,13 @@ interface PolicyModalProps { policy: PolicyData; onClose: () => void; onAgree: () => void; + t: (key: string, options?: any) => string; + lng: string; } -function PolicyModal({ policy, onClose, onAgree }: PolicyModalProps) { +function PolicyModal({ policy, onClose, onAgree, t, lng }: PolicyModalProps) { const getPolicyTitle = (policyType: string): string => { - return policyType === 'privacy_policy' ? '개인정보 처리방침' : '이용약관'; + return policyType === 'privacy_policy' ? t('privacyPolicyTitle') : t('termsOfServiceTitle'); }; return ( @@ -374,7 +391,9 @@ function PolicyModal({ policy, onClose, onAgree }: PolicyModalProps) { {getPolicyTitle(policy.policyType)} </h3> <p className="text-sm text-gray-600 mt-1"> - 버전 {policy.version} | 시행일: {new Date(policy.effectiveDate).toLocaleDateString('ko-KR')} + {t('version')} {policy.version} | {t('effectiveDate')}: {new Date(policy.effectiveDate).toLocaleDateString( + lng === 'ko' ? 'ko-KR' : 'en-US' + )} </p> </div> <button @@ -400,13 +419,13 @@ function PolicyModal({ policy, onClose, onAgree }: PolicyModalProps) { onClick={onClose} className="flex-1" > - 닫기 + {t('close')} </Button> <Button onClick={onAgree} className="flex-1" > - 동의하고 닫기 + {t('agreeAndClose')} </Button> </div> </div> |
