blessing-skin-server/resources/assets/src/views/admin/Translations/index.tsx
2020-07-04 17:12:26 +08:00

121 lines
3.2 KiB
TypeScript

import React, { useState, useEffect } from 'react'
import { hot } from 'react-hot-loader/root'
import { useImmer } from 'use-immer'
import { t } from '@/scripts/i18n'
import * as fetch from '@/scripts/net'
import { showModal, toast } from '@/scripts/notify'
import type { Paginator } from '@/scripts/types'
import Loading from '@/components/Loading'
import Pagination from '@/components/Pagination'
import type { Line } from './types'
import Row from './Row'
const Translations: React.FC = () => {
const [lines, setLines] = useImmer<Line[]>([])
const [isLoading, setIsLoading] = useState(true)
const [page, setPage] = useState(1)
const [totalPages, setTotalPages] = useState(1)
useEffect(() => {
const getLines = async () => {
setIsLoading(true)
const result = await fetch.get<Paginator<Line>>('/admin/i18n/list', {
page,
})
setLines(() => result.data)
setTotalPages(result.last_page)
setIsLoading(false)
}
getLines()
}, [page])
const handleEdit = async (line: Line, index: number) => {
let text: string
try {
const { value } = await showModal({
mode: 'prompt',
text: t('admin.i18n.updating'),
input: line.text[blessing.locale],
})
text = value
} catch {
return
}
const { code, message } = await fetch.put<fetch.ResponseBody>(
`/admin/i18n/${line.id}`,
{ text },
)
if (code === 0) {
toast.success(message)
setLines((lines) => {
lines[index].text[blessing.locale] = text
})
} else {
toast.error(message)
}
}
const handleRemove = async (line: Line) => {
try {
await showModal({
text: t('admin.i18n.confirmDelete'),
okButtonType: 'danger',
})
} catch {
return
}
const { message } = await fetch.del(`/admin/i18n/${line.id}`)
toast.success(message)
const { id } = line
setLines((lines) => lines.filter((line) => line.id !== id))
}
return (
<>
<div className="card-body p-0">
<table className="table table-striped">
<thead>
<tr>
<th>{t('admin.i18n.group')}</th>
<th>{t('admin.i18n.key')}</th>
<th>{t('admin.i18n.text')}</th>
<th>{t('admin.operationsTitle')}</th>
</tr>
</thead>
<tbody>
{isLoading ? (
<tr>
<td className="text-center" colSpan={4}>
<Loading />
</td>
</tr>
) : lines.length === 0 ? (
<tr>
<td className="text-center" colSpan={4}>
{t('general.noResult')}
</td>
</tr>
) : (
lines.map((line, i) => (
<Row
key={line.id}
line={line}
onEdit={(line) => handleEdit(line, i)}
onRemove={handleRemove}
/>
))
)}
</tbody>
</table>
</div>
<div className="card-footer d-flex flex-row-reverse">
<Pagination page={page} totalPages={totalPages} onChange={setPage} />
</div>
</>
)
}
export default hot(Translations)