Files
fuware-be/frontend/src/components/AreaInput.jsx
2024-09-02 14:28:35 +00:00

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>
</>
)
}