152 lines
4.9 KiB
JavaScript
152 lines
4.9 KiB
JavaScript
import ConfirmPopup from '@components/common/ConfirmPopup'
|
|
import Popup from '@components/common/Popup'
|
|
import TextInput from '@components/common/TextInput'
|
|
import Textarea from '@components/common/Textarea'
|
|
import { createForm } from '@felte/solid'
|
|
import { validator } from '@felte/validator-yup'
|
|
import useLanguage from '@hooks/useLanguage'
|
|
import {
|
|
IconAddressBook,
|
|
IconCirclePlus,
|
|
IconFileDescription,
|
|
IconInfoCircle,
|
|
IconVector,
|
|
} from '@tabler/icons-solidjs'
|
|
import { For, Show, createComponent, createSignal } from 'solid-js'
|
|
import * as yup from 'yup'
|
|
import AreaItem from './AreaItem'
|
|
|
|
/**
|
|
* Returns a Yup schema object for validating an area object.
|
|
*
|
|
* @param {Object} language - An object containing the language settings.
|
|
* @param {Function} isRequired - A function that returns a validation message for required fields.
|
|
* @return {Object} A Yup schema object with two required fields: name and description.
|
|
*/
|
|
const areaSchema = (language, isRequired) =>
|
|
yup.object({
|
|
name: yup.string().required(isRequired(language.ui.areaName)),
|
|
description: yup.string().required(isRequired(language.ui.areaName)),
|
|
})
|
|
|
|
export default function AreaAdd(props) {
|
|
const [openModal, setOpenModal] = createSignal(false)
|
|
const [data, setData] = createSignal([])
|
|
const { language, isRequired } = useLanguage()
|
|
const { form, reset, errors } = createForm({
|
|
extend: [validator({ schema: areaSchema(language, isRequired) })],
|
|
onSubmit: async (values) => {
|
|
setData((prev) => [...prev, values])
|
|
onModalClose()
|
|
},
|
|
})
|
|
|
|
const onModalClose = () => {
|
|
setOpenModal(false), reset()
|
|
}
|
|
|
|
const onOpenModal = () => {
|
|
setOpenModal(true)
|
|
}
|
|
|
|
const onConfirmDelete = (index) => {
|
|
setData((prev) => [...prev.slice(0, index), ...prev.slice(index + 1)])
|
|
}
|
|
|
|
const onClickDeleteItem = (index) => {
|
|
createComponent(ConfirmPopup, {
|
|
title: language?.message['CONFIRM_DELETE'],
|
|
children: language?.message['CONFIRM_DELETE_NOTE'],
|
|
deleteId: index,
|
|
onConfirm: onConfirmDelete,
|
|
})
|
|
}
|
|
|
|
return (
|
|
<div class="form-control mb-3">
|
|
<div class="join join-vertical">
|
|
<div
|
|
class="flex items-center justify-between bg-base-200 border border-gray-300 h-12 px-3 join-item"
|
|
classList={{ 'border-red-500': props.error }}
|
|
>
|
|
<label class="label justify-start gap-2">
|
|
<IconVector size={18} />
|
|
<span class="label-text font-bold whitespace-nowrap">
|
|
{language.ui.areas}
|
|
</span>
|
|
<Show when={props.error}>
|
|
<div
|
|
class="tooltip tooltip-right tooltip-error before:text-white text-red-500"
|
|
data-tip={props.error}
|
|
>
|
|
<IconInfoCircle size={18} />
|
|
</div>
|
|
</Show>
|
|
</label>
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-circle btn-xs text-green-400 hover:bg-green-100 hover:text-green-500"
|
|
onClick={onOpenModal}
|
|
>
|
|
<IconCirclePlus size={18} />
|
|
</button>
|
|
</div>
|
|
<div
|
|
class="scroll-shadow-vertical no-scrollbar border border-gray-300 join-item"
|
|
classList={{ 'border-red-500': props.error }}
|
|
>
|
|
<div class="p-3 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
<Show when={data().length > 0} fallback={language.ui.empty}>
|
|
<For each={data()}>
|
|
{(item, index) => (
|
|
<AreaItem
|
|
{...item}
|
|
formName={props.name}
|
|
key={index()}
|
|
onDelete={onClickDeleteItem}
|
|
/>
|
|
)}
|
|
</For>
|
|
</Show>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Popup
|
|
icon={<IconCirclePlus size={20} class="text-green-500" />}
|
|
title={language.ui.addArea}
|
|
titleClass="text-lg"
|
|
openModal={openModal()}
|
|
onModalClose={onModalClose}
|
|
class="!w-6/12 !max-w-5xl"
|
|
>
|
|
<form autocomplete="off" use:form>
|
|
<div class="modal-body mt-4">
|
|
<TextInput
|
|
icon={IconAddressBook}
|
|
name="name"
|
|
label={language.ui.areaName}
|
|
placeholder={language.ui.areaName}
|
|
error={errors('name')}
|
|
/>
|
|
<Textarea
|
|
icon={IconFileDescription}
|
|
name="description"
|
|
label={language.ui.areaDesc}
|
|
placeholder={language.ui.areaDesc}
|
|
error={errors('description')}
|
|
/>
|
|
</div>
|
|
<div class="modal-action">
|
|
<button type="submit" class="btn btn-primary">
|
|
{language.ui.save}
|
|
</button>
|
|
<button type="button" class="btn btn-ghost" onClick={onModalClose}>
|
|
{language.ui.cancel}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</Popup>
|
|
</div>
|
|
)
|
|
}
|