feat: services kit and copy
This commit is contained in:
@@ -1,42 +1,77 @@
|
||||
import {MultiSelect, MultiSelectProps} from "@mantine/core";
|
||||
import {useEffect, useMemo, useState} from "react";
|
||||
import {ObjectWithNameAndId} from "../../types/utils.ts";
|
||||
import {groupBy} from "lodash";
|
||||
|
||||
interface ObjectWithIdAndName {
|
||||
id: number,
|
||||
name: string
|
||||
}
|
||||
|
||||
export type MultiselectObjectType<T extends ObjectWithNameAndId> = T;
|
||||
export type MultiselectObjectType<T> = T;
|
||||
|
||||
type ControlledValueProps<T extends ObjectWithNameAndId> = {
|
||||
type ControlledValueProps<T> = {
|
||||
value: MultiselectObjectType<T>[],
|
||||
onChange: (value: MultiselectObjectType<T>[]) => void;
|
||||
}
|
||||
|
||||
type RestProps<T extends ObjectWithNameAndId> = {
|
||||
type CustomLabelAndKeyProps<T> = {
|
||||
getLabelFn: (item: MultiselectObjectType<T>) => string;
|
||||
getValueFn: (item: MultiselectObjectType<T>) => string;
|
||||
}
|
||||
type RestProps<T> = {
|
||||
defaultValue?: MultiselectObjectType<T>[]
|
||||
onChange: (value: MultiselectObjectType<T>[]) => void;
|
||||
data: MultiselectObjectType<T>[];
|
||||
groupBy?: (item: MultiselectObjectType<T>) => string;
|
||||
filterBy?: (item: MultiselectObjectType<T>) => boolean;
|
||||
}
|
||||
const defaultGetLabelFn = <T extends { name: string }>(item: T): string => {
|
||||
return item.name;
|
||||
}
|
||||
|
||||
export type ObjectMultiSelectProps<T extends ObjectWithNameAndId> =
|
||||
const defaultGetValueFn = <T extends { id: number }>(item: T): string => {
|
||||
return item.id.toString();
|
||||
}
|
||||
export type ObjectMultiSelectProps<T> =
|
||||
(RestProps<T> & Partial<ControlledValueProps<T>>)
|
||||
& Omit<MultiSelectProps, 'value' | 'onChange' | 'data'>;
|
||||
& Omit<MultiSelectProps, 'value' | 'onChange' | 'data'>
|
||||
& (T extends ObjectWithIdAndName ? Partial<CustomLabelAndKeyProps<T>> : CustomLabelAndKeyProps<T>);
|
||||
|
||||
const ObjectMultiSelect = <T extends ObjectWithNameAndId, >(props: ObjectMultiSelectProps<T>) => {
|
||||
const ObjectMultiSelect = <T, >(props: ObjectMultiSelectProps<T>) => {
|
||||
|
||||
const isControlled = 'value' in props;
|
||||
const haveGetValueFn = 'getValueFn' in props;
|
||||
const haveGetLabelFn = 'getLabelFn' in props;
|
||||
|
||||
const [internalValue, setInternalValue] = useState<MultiselectObjectType<T>[] | undefined>(props.defaultValue);
|
||||
|
||||
const value = (isControlled ? props.value : internalValue) || [];
|
||||
|
||||
const data = useMemo(() => props.data.reduce((acc, item) => {
|
||||
acc.push({
|
||||
label: item.name,
|
||||
value: item.id.toString()
|
||||
});
|
||||
return acc;
|
||||
}, [] as { label: string, value: string }[]), [props.data]);
|
||||
const getValueFn = (haveGetValueFn && props.getValueFn) || defaultGetValueFn;
|
||||
const getLabelFn = (haveGetLabelFn && props.getLabelFn) || defaultGetLabelFn;
|
||||
|
||||
const data = useMemo(() => {
|
||||
const propsData = props.filterBy ? props.data.filter(props.filterBy) : props.data;
|
||||
if (props.groupBy) {
|
||||
|
||||
const groupedData = groupBy(propsData, props.groupBy);
|
||||
return Object.entries(groupedData).map(([group, items]) => ({
|
||||
group,
|
||||
items: items.map(item => ({
|
||||
label: getLabelFn(item),
|
||||
value: getValueFn(item)
|
||||
}))
|
||||
}));
|
||||
} else {
|
||||
return propsData.map(item => ({
|
||||
label: getLabelFn(item),
|
||||
value: getValueFn(item)
|
||||
}));
|
||||
}
|
||||
}, [props.data, props.groupBy]);
|
||||
|
||||
const handleOnChange = (event: string[]) => {
|
||||
const objects = props.data.filter(item => event.includes(item.id.toString()));
|
||||
const objects = props.data.filter(item => event.includes(getValueFn(item)));
|
||||
if (isControlled) {
|
||||
props.onChange(objects);
|
||||
return;
|
||||
@@ -51,7 +86,7 @@ const ObjectMultiSelect = <T extends ObjectWithNameAndId, >(props: ObjectMultiSe
|
||||
return (
|
||||
<MultiSelect
|
||||
{...props}
|
||||
value={value.map(item => item.id.toString())}
|
||||
value={value.map(item => getValueFn(item))}
|
||||
onChange={handleOnChange}
|
||||
data={data}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import ObjectSelect, {ObjectSelectProps} from "../../ObjectSelect/ObjectSelect.tsx";
|
||||
import {GetServiceKitSchema} from "../../../client";
|
||||
import {FC} from "react";
|
||||
import useServicesKitsList from "../../../pages/ServicesPage/hooks/useServicesKitsList.tsx";
|
||||
|
||||
type Props = Omit<ObjectSelectProps<GetServiceKitSchema>, 'data'>
|
||||
const ServicesKitSelect: FC<Props> = (props) => {
|
||||
const {objects} = useServicesKitsList();
|
||||
return (
|
||||
<ObjectSelect
|
||||
data={objects}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ServicesKitSelect;
|
||||
@@ -0,0 +1,16 @@
|
||||
import ObjectMultiSelect, {ObjectMultiSelectProps} from "../../ObjectMultiSelect/ObjectMultiSelect.tsx";
|
||||
import {ServiceSchema} from "../../../client";
|
||||
import {FC} from "react";
|
||||
import useServicesList from "../../../pages/ServicesPage/hooks/useServicesList.tsx";
|
||||
|
||||
type Props = Omit<ObjectMultiSelectProps<ServiceSchema>, 'data'>
|
||||
const ServicesMultiselect: FC<Props> = (props: Props) => {
|
||||
const {services} = useServicesList();
|
||||
return (
|
||||
<ObjectMultiSelect
|
||||
data={services}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
export default ServicesMultiselect;
|
||||
Reference in New Issue
Block a user