Completed Change to ReactJS
This commit is contained in:
181
frontend/src/components/AreaInput.jsx
Normal file
181
frontend/src/components/AreaInput.jsx
Normal file
@@ -0,0 +1,181 @@
|
||||
import {
|
||||
ActionIcon,
|
||||
Button,
|
||||
Grid,
|
||||
Group,
|
||||
InputWrapper,
|
||||
Modal,
|
||||
Text,
|
||||
Textarea,
|
||||
TextInput,
|
||||
} from '@mantine/core'
|
||||
import { useForm, yupResolver } from '@mantine/form'
|
||||
import { useDisclosure, useMediaQuery } from '@mantine/hooks'
|
||||
import {
|
||||
IconAddressBook,
|
||||
IconCirclePlus,
|
||||
IconFileDescription,
|
||||
} from '@tabler/icons-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import * as yup from 'yup'
|
||||
import AreaItem from './AreaItem'
|
||||
import { errorTip, labelWithIcon } from './Common'
|
||||
|
||||
const areaSchema = (t) =>
|
||||
yup.object({
|
||||
name: yup
|
||||
.string()
|
||||
.min(3, t('message_min_three_char'))
|
||||
.required(t('message_is_required', { field: t('ui_area_name') })),
|
||||
desc: yup
|
||||
.string()
|
||||
.min(3, t('message_min_three_char'))
|
||||
.required(t('message_is_required', { field: t('ui_area_desc') })),
|
||||
})
|
||||
|
||||
export default function AreaInput(props) {
|
||||
const { t } = useTranslation()
|
||||
const [editData, setEditData] = useState(null)
|
||||
const [opened, { open, close }] = useDisclosure(false)
|
||||
const isMobile = useMediaQuery('(max-width: 62em)')
|
||||
const { value, onChange, error } = props
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
name: '',
|
||||
desc: '',
|
||||
},
|
||||
validate: yupResolver(areaSchema(t)),
|
||||
enhanceGetInputProps: (payload) => ({
|
||||
error: errorTip(payload.inputProps.error),
|
||||
}),
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (editData) {
|
||||
form.setValues(editData)
|
||||
}
|
||||
}, [editData])
|
||||
|
||||
const onCloseModal = () => {
|
||||
form.reset()
|
||||
setEditData(null)
|
||||
close()
|
||||
}
|
||||
|
||||
const addArea = (area) => {
|
||||
area.id = uuidv4()
|
||||
area.isCreate = true
|
||||
onChange([...value, area])
|
||||
onCloseModal()
|
||||
}
|
||||
|
||||
const updateArea = (area) => {
|
||||
onChange(value.map((item) => (item.id === area.id ? area : item)))
|
||||
form.reset()
|
||||
onCloseModal()
|
||||
}
|
||||
|
||||
const onEditArea = (area) => {
|
||||
setEditData(area)
|
||||
open()
|
||||
}
|
||||
|
||||
const onDeleteArea = (area) => {
|
||||
onChange(value.filter((item) => item.id !== area.id))
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<InputWrapper label={props.label} error={error}>
|
||||
<ActionIcon
|
||||
variant="transparent"
|
||||
size="sm"
|
||||
style={{ gridArea: 'right', justifySelf: 'end' }}
|
||||
onClick={open}
|
||||
>
|
||||
<IconCirclePlus size={20} color="var(--mantine-color-green-6)" />
|
||||
</ActionIcon>
|
||||
<Grid
|
||||
gutter="md"
|
||||
my={5}
|
||||
p="sm"
|
||||
bd={`1px solid ${error ? 'red.5' : 'gray.4'}`}
|
||||
style={{
|
||||
gridArea: 'input',
|
||||
borderRadius: 'var(--mantine-radius-default)',
|
||||
borderColor: '',
|
||||
}}
|
||||
>
|
||||
{value.length > 0 ? (
|
||||
value.map((area) => (
|
||||
<Grid.Col key={area.id} span={{ base: 12, md: 6, lg: 4 }}>
|
||||
<AreaItem
|
||||
data={area}
|
||||
onEdit={onEditArea}
|
||||
onDelete={onDeleteArea}
|
||||
/>
|
||||
</Grid.Col>
|
||||
))
|
||||
) : (
|
||||
<Grid.Col span={12}>
|
||||
<Text size="xs" fw={500}>
|
||||
{t('ui_empty')}
|
||||
</Text>
|
||||
</Grid.Col>
|
||||
)}
|
||||
</Grid>
|
||||
</InputWrapper>
|
||||
<Modal
|
||||
opened={opened}
|
||||
onClose={onCloseModal}
|
||||
title={labelWithIcon(t('ui_add_area'), IconCirclePlus, {
|
||||
color: 'green',
|
||||
})}
|
||||
centered
|
||||
radius="lg"
|
||||
fullScreen={isMobile}
|
||||
transitionProps={{ transition: 'fade', duration: 200 }}
|
||||
>
|
||||
<form autoComplete="off">
|
||||
<TextInput
|
||||
label={labelWithIcon(t('ui_area_name'), IconAddressBook)}
|
||||
placeholder={t('ui_area_name')}
|
||||
withAsterisk
|
||||
mb="md"
|
||||
data-autofocus
|
||||
{...form.getInputProps('name')}
|
||||
/>
|
||||
<Textarea
|
||||
label={labelWithIcon(t('ui_area_desc'), IconFileDescription)}
|
||||
placeholder={t('ui_area_desc')}
|
||||
withAsterisk
|
||||
rows={4}
|
||||
{...form.getInputProps('desc')}
|
||||
/>
|
||||
<Group mt="md">
|
||||
{editData ? (
|
||||
<Button type="button" onClick={form.onSubmit(updateArea)}>
|
||||
{t('ui_update')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button type="button" onClick={form.onSubmit(addArea)}>
|
||||
{t('ui_save')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
color="red"
|
||||
type="button"
|
||||
onClick={onCloseModal}
|
||||
>
|
||||
{t('ui_cancel')}
|
||||
</Button>
|
||||
</Group>
|
||||
</form>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user