dramaling-vocab-learning/frontend/components/generate/IdiomDetailModal.tsx

132 lines
4.1 KiB
TypeScript

import React, { useState } from 'react'
import { Modal } from '@/components/ui/Modal'
import { ContentBlock } from '@/components/shared/ContentBlock'
import { BluePlayButton } from '@/components/shared/BluePlayButton'
interface IdiomAnalysis {
idiom: string
translation: string
definition: string
pronunciation?: string
cefr?: string
example?: string
exampleTranslation?: string
synonyms?: string[]
[key: string]: any
}
interface IdiomPopup {
idiom: string
analysis: IdiomAnalysis
position: { x: number; y: number }
}
interface IdiomDetailModalProps {
idiomPopup: IdiomPopup | null
onClose: () => void
onSaveIdiom?: (idiom: string, analysis: IdiomAnalysis) => Promise<{ success: boolean; error?: string }>
className?: string
}
export const IdiomDetailModal: React.FC<IdiomDetailModalProps> = ({
idiomPopup,
onClose,
onSaveIdiom,
className = ''
}) => {
if (!idiomPopup) {
return null
}
const { analysis } = idiomPopup
const handleSave = async () => {
if (onSaveIdiom) {
await onSaveIdiom(idiomPopup.idiom, analysis)
}
}
return (
<Modal isOpen={!!idiomPopup} onClose={onClose} size="md">
{/* Header */}
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 p-5 border-b border-blue-200">
<div className="mb-3">
<h3 className="text-2xl font-bold text-gray-900">{analysis.idiom}</h3>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<span className="text-base text-gray-600">{analysis.pronunciation}</span>
<BluePlayButton
text={analysis.idiom}
lang="en-US"
size="sm"
title="播放發音"
/>
</div>
</div>
<span className="px-3 py-1 rounded-full text-sm font-medium border bg-blue-100 text-blue-700 border-blue-200">
{analysis.cefr || 'A1'}
</span>
</div>
</div>
{/* Content */}
<div className="p-4 space-y-4 max-h-96 overflow-y-auto">
{/* Translation */}
<ContentBlock title="中文翻譯" variant="green">
<p className="text-green-800 font-medium text-left">{analysis.translation}</p>
</ContentBlock>
{/* Definition */}
<ContentBlock title="英文定義" variant="gray">
<p className="text-gray-700 text-left text-sm leading-relaxed">{analysis.definition}</p>
</ContentBlock>
{/* Example */}
{analysis.example && (
<ContentBlock title="例句" variant="blue">
<div className="space-y-2">
<p className="text-blue-800 text-left text-sm italic">
"{analysis.example}"
</p>
<p className="text-blue-700 text-left text-sm">
{analysis.exampleTranslation}
</p>
</div>
</ContentBlock>
)}
{/* Synonyms */}
{analysis.synonyms && Array.isArray(analysis.synonyms) && analysis.synonyms.length > 0 && (
<ContentBlock title="相關詞彙" variant="purple">
<div className="flex flex-wrap gap-2">
{analysis.synonyms.map((synonym: string, index: number) => (
<span
key={index}
className="bg-purple-100 text-purple-700 px-2 py-1 rounded-full text-xs font-medium"
>
{synonym}
</span>
))}
</div>
</ContentBlock>
)}
</div>
{/* Save Button */}
{onSaveIdiom && (
<div className="p-4 pt-2">
<button
onClick={handleSave}
className="w-full bg-primary text-white py-3 rounded-lg font-medium hover:bg-primary-hover transition-colors flex items-center justify-center gap-2"
>
<span className="font-medium"></span>
</button>
</div>
)}
</Modal>
)
}