fix(dictionary): let an edit clear the pronunciation and report duplicate renames
This commit is contained in:
parent
9d5d043e8b
commit
de1e8a82a4
6 changed files with 350 additions and 24 deletions
|
|
@ -9,6 +9,11 @@ import { PageHeader, SearchInput, EmptyStateCard } from '../components/shared'
|
|||
import { d3roPalette, d3roFontSans, d3roTypo, d3roRadius, d3roShadow } from '@d3ro/ui/theme'
|
||||
import { useI18n } from '@d3ro/i18n'
|
||||
import type { DictionaryEntry, DictionaryPage as DictPageData } from '@d3ro/core/types'
|
||||
import {
|
||||
dictionarySaveErrorKey,
|
||||
toDictionaryAddParams,
|
||||
toDictionaryUpdateParams,
|
||||
} from '@d3ro/core/dictionary-policy'
|
||||
|
||||
export function DictionaryPage(): React.ReactElement {
|
||||
const { t } = useI18n()
|
||||
|
|
@ -20,6 +25,7 @@ export function DictionaryPage(): React.ReactElement {
|
|||
const [formWord, setFormWord] = useState('')
|
||||
const [formPronunciation, setFormPronunciation] = useState('')
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [formError, setFormError] = useState<string | null>(null)
|
||||
const isSavingRef = useRef(false)
|
||||
const [ioBusy, setIoBusy] = useState(false)
|
||||
const [ioMessage, setIoMessage] = useState<string | null>(null)
|
||||
|
|
@ -47,6 +53,7 @@ export function DictionaryPage(): React.ReactElement {
|
|||
setEditId(null)
|
||||
setFormWord('')
|
||||
setFormPronunciation('')
|
||||
setFormError(null)
|
||||
setDialogOpen(true)
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +62,7 @@ export function DictionaryPage(): React.ReactElement {
|
|||
setEditId(entry.id)
|
||||
setFormWord(entry.word)
|
||||
setFormPronunciation(entry.pronunciation ?? '')
|
||||
setFormError(null)
|
||||
setDialogOpen(true)
|
||||
}
|
||||
|
||||
|
|
@ -62,18 +70,16 @@ export function DictionaryPage(): React.ReactElement {
|
|||
if (!formWord.trim() || saving || isSavingRef.current) return
|
||||
isSavingRef.current = true
|
||||
setSaving(true)
|
||||
setFormError(null)
|
||||
try {
|
||||
if (editId) {
|
||||
await window.electronAPI.dictionary.update({
|
||||
id: editId,
|
||||
word: formWord.trim(),
|
||||
pronunciation: formPronunciation.trim() || undefined,
|
||||
})
|
||||
} else {
|
||||
await window.electronAPI.dictionary.add({
|
||||
word: formWord.trim(),
|
||||
pronunciation: formPronunciation.trim() || undefined,
|
||||
})
|
||||
const form = { word: formWord, pronunciation: formPronunciation }
|
||||
const result = editId
|
||||
? await window.electronAPI.dictionary.update(toDictionaryUpdateParams(editId, form))
|
||||
: await window.electronAPI.dictionary.add(toDictionaryAddParams(form))
|
||||
if (!result.success) {
|
||||
// 다이얼로그를 유지해 사용자가 입력을 고칠 수 있게 한다 (예: 같은 단어로 이름 변경).
|
||||
setFormError(t(dictionarySaveErrorKey(result.error.code)))
|
||||
return
|
||||
}
|
||||
setDialogOpen(false)
|
||||
loadData()
|
||||
|
|
@ -308,7 +314,11 @@ export function DictionaryPage(): React.ReactElement {
|
|||
<TextField
|
||||
label={t('dictionary.word')}
|
||||
value={formWord}
|
||||
onChange={(e) => setFormWord(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setFormWord(e.target.value)
|
||||
setFormError(null)
|
||||
}}
|
||||
error={formError !== null}
|
||||
fullWidth
|
||||
autoFocus
|
||||
sx={{ mt: 1.5 }}
|
||||
|
|
@ -321,13 +331,18 @@ export function DictionaryPage(): React.ReactElement {
|
|||
sx={{ mt: 2.5 }}
|
||||
helperText="e.g. 디쓰리오"
|
||||
/>
|
||||
{formError && (
|
||||
<PhosphorText variant="meta" role="alert" sx={{ display: 'block', mt: 1.5, color: d3roPalette.tag.red }}>
|
||||
{formError}
|
||||
</PhosphorText>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ px: 2.5, pb: 2, pt: 1, gap: 1 }}>
|
||||
<PhysicalButton tone="glass" onClick={() => setDialogOpen(false)}>
|
||||
{t('common.cancel')}
|
||||
</PhysicalButton>
|
||||
<PhysicalButton tone="accent" onClick={handleSave} disabled={!formWord.trim() || saving}>
|
||||
{saving ? t('common.saving') || '저장 중...' : t('common.save')}
|
||||
{saving ? t('common.saving') : t('common.save')}
|
||||
</PhysicalButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue