182 lines
4.6 KiB
JavaScript
182 lines
4.6 KiB
JavaScript
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>
|
|
</>
|
|
)
|
|
}
|