feat: deal attributes with select and options
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import { CSSProperties, FC, JSX } from "react";
|
||||
import { Checkbox, NumberInput, TextInput } from "@mantine/core";
|
||||
import { DatePickerInput, DateTimePicker } from "@mantine/dates";
|
||||
import AttrOptionSelect from "@/app/module-editor/[moduleId]/components/shared/AttrOptionSelect/AttrOptionSelect";
|
||||
import { DealModuleAttributeSchema } from "@/lib/client";
|
||||
import { naiveDateTimeStringToUtc } from "@/utils/datetime";
|
||||
|
||||
@ -25,15 +26,13 @@ const AttributeValueInput: FC<Props> = ({
|
||||
error,
|
||||
};
|
||||
|
||||
const renderCheckbox = () => {
|
||||
return (
|
||||
<Checkbox
|
||||
{...commonProps}
|
||||
checked={Boolean(value)}
|
||||
onChange={e => onChange(e.currentTarget.checked)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const renderCheckbox = () => (
|
||||
<Checkbox
|
||||
{...commonProps}
|
||||
checked={Boolean(value)}
|
||||
onChange={e => onChange(e.currentTarget.checked)}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderDatePicker = () => (
|
||||
<DatePickerInput
|
||||
@ -84,6 +83,18 @@ const AttributeValueInput: FC<Props> = ({
|
||||
/>
|
||||
);
|
||||
|
||||
const renderSelect = () => {
|
||||
if (!attrInfo.select?.id) return <></>;
|
||||
return (
|
||||
<AttrOptionSelect
|
||||
{...commonProps}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
selectId={attrInfo.select.id}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderingFuncMap: Record<string, () => JSX.Element> = {
|
||||
bool: renderCheckbox,
|
||||
date: renderDatePicker,
|
||||
@ -91,6 +102,7 @@ const AttributeValueInput: FC<Props> = ({
|
||||
str: renderTextInput,
|
||||
int: renderNumberInput,
|
||||
float: renderNumberInput,
|
||||
select: renderSelect,
|
||||
};
|
||||
|
||||
const render = renderingFuncMap[attrInfo.type.type];
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { omit } from "lodash";
|
||||
import useAttributeOptionsList from "@/app/module-editor/[moduleId]/components/shared/AttrOptionSelect/useAttributeOptionsList";
|
||||
import ObjectSelect from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||
import { AttrOptionSchema } from "@/lib/client";
|
||||
|
||||
type Props = {
|
||||
value: any;
|
||||
onChange: (val: any) => void;
|
||||
selectId: number;
|
||||
error?: string;
|
||||
label?: string;
|
||||
};
|
||||
|
||||
const AttrOptionSelect = (props: Props) => {
|
||||
const { options } = useAttributeOptionsList(props);
|
||||
|
||||
const [selectedOption, setSelectedOption] = useState<AttrOptionSchema>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.value) {
|
||||
setSelectedOption(undefined);
|
||||
return;
|
||||
}
|
||||
setSelectedOption(options.find(option => option.value === props.value));
|
||||
}, [props.value, options]);
|
||||
|
||||
const restProps = omit(props, ["value, onChange", "selectId"]);
|
||||
|
||||
return (
|
||||
<ObjectSelect
|
||||
label={"Значение"}
|
||||
{...restProps}
|
||||
data={options}
|
||||
value={selectedOption}
|
||||
onChange={option => {
|
||||
setSelectedOption(option);
|
||||
props.onChange(option.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
setSelectedOption(undefined);
|
||||
props.onChange(null);
|
||||
}}
|
||||
getLabelFn={option => option.label}
|
||||
clearable
|
||||
searchable
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AttrOptionSelect;
|
||||
@ -0,0 +1,19 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getAttrSelectOptionsOptions } from "@/lib/client/@tanstack/react-query.gen";
|
||||
|
||||
type Props = {
|
||||
selectId: number;
|
||||
};
|
||||
|
||||
const useAttributeSelectsList = ({ selectId }: Props) => {
|
||||
const { data, refetch } = useQuery(
|
||||
getAttrSelectOptionsOptions({ path: { selectId } })
|
||||
);
|
||||
|
||||
return {
|
||||
options: data?.items ?? [],
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
export default useAttributeSelectsList;
|
||||
@ -0,0 +1,24 @@
|
||||
import ObjectSelect, { ObjectSelectProps } from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||
import { AttributeSelectSchema } from "@/lib/client";
|
||||
import useAttributeSelectsList from "./useAttributeSelectsList";
|
||||
|
||||
|
||||
type Props = Omit<
|
||||
ObjectSelectProps<AttributeSelectSchema>,
|
||||
"data" | "getLabelFn"
|
||||
>;
|
||||
|
||||
const AttrSelectSelect = (props: Props) => {
|
||||
const { selects } = useAttributeSelectsList();
|
||||
|
||||
return (
|
||||
<ObjectSelect
|
||||
label={"Объект для выбора"}
|
||||
getLabelFn={select => select.label}
|
||||
data={selects}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AttrSelectSelect;
|
||||
@ -0,0 +1,13 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getAttrSelectsOptions } from "@/lib/client/@tanstack/react-query.gen";
|
||||
|
||||
const useAttributeSelectsList = () => {
|
||||
const { data, refetch } = useQuery(getAttrSelectsOptions());
|
||||
|
||||
return {
|
||||
selects: data?.items ?? [],
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
export default useAttributeSelectsList;
|
||||
@ -20,6 +20,10 @@ const useAttributesTableColumns = () => {
|
||||
{
|
||||
title: "Тип",
|
||||
accessor: "type.name",
|
||||
render: attr =>
|
||||
attr.type.type === "select"
|
||||
? `Выбор "${attr.label}"`
|
||||
: attr.type.name,
|
||||
},
|
||||
{
|
||||
accessor: "actions",
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { Checkbox, NumberInput, TextInput } from "@mantine/core";
|
||||
import { DatePickerInput, DateTimePicker } from "@mantine/dates";
|
||||
import { UseFormReturnType } from "@mantine/form";
|
||||
import { UpdateAttributeSchema } from "@/lib/client";
|
||||
import AttrOptionSelect from "@/app/module-editor/[moduleId]/components/shared/AttrOptionSelect/AttrOptionSelect";
|
||||
import { AttributeSchema } from "@/lib/client";
|
||||
import { naiveDateTimeStringToUtc } from "@/utils/datetime";
|
||||
|
||||
type Props = {
|
||||
form: UseFormReturnType<Partial<UpdateAttributeSchema>>;
|
||||
form: UseFormReturnType<Partial<AttributeSchema>>;
|
||||
};
|
||||
|
||||
const DefaultAttributeValueInput = ({ form }: Props) => {
|
||||
@ -87,8 +88,18 @@ const DefaultAttributeValueInput = ({ form }: Props) => {
|
||||
}
|
||||
/>
|
||||
);
|
||||
} else if (type === "select") {
|
||||
if (!form.values.select?.id) return <></>;
|
||||
return (
|
||||
<AttrOptionSelect
|
||||
label={"Значение по умолчанию"}
|
||||
{...form.getInputProps("defaultValue")}
|
||||
value={form.values.defaultValue}
|
||||
onChange={value => form.setFieldValue("defaultValue", value)}
|
||||
selectId={form.values.select?.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
|
||||
@ -40,7 +40,10 @@ const ModuleAttribute: FC<Props> = ({ attribute }) => {
|
||||
align={"center"}>
|
||||
<Stack gap={7}>
|
||||
<>{getAttrLabelText()}</>
|
||||
<Text>Тип: {attribute.type.name}</Text>
|
||||
<Text>
|
||||
Тип: {attribute.type.name}{" "}
|
||||
{attribute.select && `"${attribute.select.label}"`}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Group
|
||||
justify={"end"}
|
||||
|
||||
@ -5,6 +5,7 @@ import { Checkbox, Stack, Textarea, TextInput } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { ContextModalProps } from "@mantine/modals";
|
||||
import AttributeTypeSelect from "@/app/module-editor/[moduleId]/components/shared/AttributeTypeSelect/AttributeTypeSelect";
|
||||
import AttrSelectSelect from "@/app/module-editor/[moduleId]/components/shared/AttrSelectSelect/AttrSelectSelect";
|
||||
import DefaultAttributeValueInput from "@/app/module-editor/[moduleId]/components/shared/DefaultAttributeValueInput/DefaultAttributeValueInput";
|
||||
import {
|
||||
AttributeSchema,
|
||||
@ -30,7 +31,7 @@ const AttributeEditorModal = ({
|
||||
const [isNullableInputShown, setIsNullableInputShown] = useState(true);
|
||||
const [copyTypeId, setCopyTypeId] = useState<number>();
|
||||
|
||||
const form = useForm<Partial<UpdateAttributeSchema>>({
|
||||
const form = useForm<any>({
|
||||
initialValues: innerProps.isEditing
|
||||
? innerProps.entity
|
||||
: ({
|
||||
@ -38,11 +39,13 @@ const AttributeEditorModal = ({
|
||||
name: "",
|
||||
typeId: undefined,
|
||||
type: undefined,
|
||||
selectId: undefined,
|
||||
select: undefined,
|
||||
isApplicableToGroup: false,
|
||||
isNullable: false,
|
||||
defaultValue: null,
|
||||
description: "",
|
||||
} as Partial<CreateAttributeSchema>),
|
||||
} as Partial<AttributeSchema>),
|
||||
validate: {
|
||||
label: label => !label?.trim() && "Название не заполнено",
|
||||
type: type => !type && "Тип атрибута не выбран",
|
||||
@ -62,7 +65,7 @@ const AttributeEditorModal = ({
|
||||
if (!isInitial) {
|
||||
if (type === "bool") {
|
||||
form.setFieldValue("isNullable", false);
|
||||
form.setFieldValue("defaultValue", { value: false });
|
||||
form.setFieldValue("defaultValue", false);
|
||||
} else {
|
||||
form.setFieldValue("defaultValue", null);
|
||||
}
|
||||
@ -88,10 +91,27 @@ const AttributeEditorModal = ({
|
||||
disabled={innerProps.isEditing}
|
||||
{...form.getInputProps("type")}
|
||||
onChange={type => {
|
||||
if (type.type !== "select") {
|
||||
form.setFieldValue("select", undefined);
|
||||
form.setFieldValue("selectId", undefined);
|
||||
}
|
||||
form.setFieldValue("type", type);
|
||||
form.setFieldValue("typeId", type.id);
|
||||
}}
|
||||
/>
|
||||
{form.values.type?.type === "select" && (
|
||||
<AttrSelectSelect
|
||||
withAsterisk
|
||||
searchable
|
||||
disabled={innerProps.isEditing}
|
||||
{...form.getInputProps("select")}
|
||||
onChange={select => {
|
||||
form.setFieldValue("select", select);
|
||||
form.setFieldValue("selectId", select.id);
|
||||
form.setFieldValue("defaultValue", null);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Checkbox
|
||||
label={"Значение синхронизировано в группе"}
|
||||
{...form.getInputProps("isApplicableToGroup", {
|
||||
|
||||
@ -27,6 +27,10 @@ const useAttributesInnerTableColumns = () => {
|
||||
{
|
||||
title: "Тип",
|
||||
accessor: "type.name",
|
||||
render: attr =>
|
||||
attr.type.type === "select"
|
||||
? `Выбор "${attr.label}"`
|
||||
: attr.type.name,
|
||||
},
|
||||
{
|
||||
title: "Значение по умолчанию",
|
||||
|
||||
Reference in New Issue
Block a user