feat: services kits table in service page

This commit is contained in:
2025-09-25 09:36:22 +04:00
parent a83328492e
commit 14140826a7
28 changed files with 641 additions and 32 deletions

View File

@ -15,6 +15,8 @@
--dark-thick-shadow: 1px 1px 13px 1px var(--mantine-color-dark-5); --dark-thick-shadow: 1px 1px 13px 1px var(--mantine-color-dark-5);
/* Heights */ /* Heights */
--page-height: calc(100vh - (var(--mantine-spacing-md) * 2)); --page-height: calc(100vh - (var(--mantine-spacing-md) * 2));
--mobile-footer-height: 70px;
--mobile-page-height: calc(100vh - var(--mobile-footer-height));
} }
body { body {

View File

@ -0,0 +1,27 @@
import { FC } from "react";
import { ButtonProps } from "@mantine/core";
import { modals } from "@mantine/modals";
import { useServicesContext } from "@/app/services/contexts/ServicesContext";
import InlineButton from "@/components/ui/InlineButton/InlineButton";
type Props = ButtonProps;
const CreateServiceKitButton: FC<Props> = () => {
const { servicesKitCrud } = useServicesContext();
const onCreateClick = () => {
modals.openContextModal({
modal: "servicesKitEditorModal",
title: "Создание набора услуг",
withCloseButton: false,
innerProps: {
onCreate: servicesKitCrud.onCreate,
isEditing: false,
},
});
};
return <InlineButton onClick={onCreateClick}>Создать набор</InlineButton>;
};
export default CreateServiceKitButton;

View File

@ -0,0 +1,45 @@
"use client";
import { FC } from "react";
import { Box, Group } from "@mantine/core";
import CreateServiceKitButton from "@/app/services/components/desktop/CreateServiceKitButton/CreateServiceKitButton";
import ServiceTabSegmentedControl, {
ServicesTab,
} from "@/app/services/components/shared/ServiceTabSegmentedControl/ServiceTabSegmentedControl";
type Props = {
serviceTab: ServicesTab;
onServiceTabChange: (serviceTab: ServicesTab) => void;
};
const ServicesDesktopHeader: FC<Props> = ({
serviceTab,
onServiceTabChange,
}) => {
const getTabActions = () => {
switch (serviceTab) {
case ServicesTab.DEAL_SERVICE:
return <Box />;
case ServicesTab.PRODUCT_SERVICE:
return <Box />;
case ServicesTab.SERVICES_KITS:
return <CreateServiceKitButton />;
default:
return <Box />;
}
};
return (
<Group
wrap={"nowrap"}
justify={"space-between"}>
{getTabActions()}
<ServiceTabSegmentedControl
value={serviceTab.toString()}
onChange={tab => onServiceTabChange(Number(tab))}
/>
</Group>
);
};
export default ServicesDesktopHeader;

View File

@ -0,0 +1,28 @@
"use client";
import { FC } from "react";
import ServiceTabSegmentedControl, {
ServicesTab,
} from "@/app/services/components/shared/ServiceTabSegmentedControl/ServiceTabSegmentedControl";
type Props = {
serviceTab: ServicesTab;
onServiceTabChange: (serviceTab: ServicesTab) => void;
};
const ServicesMobileHeader: FC<Props> = ({
serviceTab,
onServiceTabChange,
}) => {
return (
<ServiceTabSegmentedControl
value={serviceTab.toString()}
onChange={tab => onServiceTabChange(Number(tab))}
w={"100%"}
py={"md"}
px={"sm"}
/>
);
};
export default ServicesMobileHeader;

View File

@ -0,0 +1,63 @@
"use client";
import { useState } from "react";
import ServicesDesktopHeader from "@/app/services/components/desktop/ServicesDesktopHeader/ServicesDesktopHeader";
import ServicesMobileHeader from "@/app/services/components/mobile/ServicesMobileHeader/ServicesMobileHeader";
import ServicesKitsTable from "@/app/services/components/shared/ServicesKitTable/ServicesKitTable";
import { ServicesTab } from "@/app/services/components/shared/ServiceTabSegmentedControl/ServiceTabSegmentedControl";
import PageBlock from "@/components/layout/PageBlock/PageBlock";
import useIsMobile from "@/hooks/utils/useIsMobile";
const PageBody = () => {
const isMobile = useIsMobile();
const [servicesTab, setServicesTab] = useState<ServicesTab>(
ServicesTab.PRODUCT_SERVICE
);
const getPageBody = () => {
switch (servicesTab) {
case ServicesTab.PRODUCT_SERVICE:
return <></>;
case ServicesTab.DEAL_SERVICE:
return <></>;
case ServicesTab.SERVICES_KITS:
return <ServicesKitsTable />;
default:
return <>-</>;
}
};
return (
<>
{!isMobile && (
<PageBlock>
<ServicesDesktopHeader
serviceTab={servicesTab}
onServiceTabChange={setServicesTab}
/>
</PageBlock>
)}
<PageBlock fullHeight>
<div
style={{
height: "100%",
display: "flex",
flexDirection: "column",
}}>
{isMobile && (
<ServicesMobileHeader
serviceTab={servicesTab}
onServiceTabChange={setServicesTab}
/>
)}
<div style={{ flex: 1, overflow: "auto" }}>
{getPageBody()}
</div>
</div>
</PageBlock>
</>
);
};
export default PageBody;

View File

@ -0,0 +1,34 @@
import { FC } from "react";
import { SegmentedControl, SegmentedControlProps } from "@mantine/core";
export enum ServicesTab {
DEAL_SERVICE,
PRODUCT_SERVICE,
SERVICES_KITS,
}
type Props = Omit<SegmentedControlProps, "data">;
const data = [
{
label: "Для товара",
value: ServicesTab.PRODUCT_SERVICE.toString(),
},
{
label: "Для сделки",
value: ServicesTab.DEAL_SERVICE.toString(),
},
{
label: "Наборы услуг",
value: ServicesTab.SERVICES_KITS.toString(),
},
];
const ServiceTabSegmentedControl: FC<Props> = props => (
<SegmentedControl
data={data}
{...props}
/>
);
export default ServiceTabSegmentedControl;

View File

@ -0,0 +1,25 @@
import { FC } from "react";
import { SegmentedControl, SegmentedControlProps } from "@mantine/core";
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
type Props = Omit<SegmentedControlProps, "data">;
const data = [
{
label: "Для сделки",
value: ServiceType.DEAL_SERVICE.toString(),
},
{
label: "Для товара",
value: ServiceType.PRODUCT_SERVICE.toString(),
},
];
const ServiceTypeSegmentedControl: FC<Props> = props => (
<SegmentedControl
data={data}
{...props}
/>
);
export default ServiceTypeSegmentedControl;

View File

@ -0,0 +1,42 @@
import { modals } from "@mantine/modals";
import useServicesKitsTableColumns from "@/app/services/components/shared/ServicesKitTable/hooks/useServicesKitsTableColumns";
import { useServicesContext } from "@/app/services/contexts/ServicesContext";
import BaseTable from "@/components/ui/BaseTable/BaseTable";
import useIsMobile from "@/hooks/utils/useIsMobile";
import { ServicesKitSchema } from "@/lib/client";
const ServicesKitsTable = () => {
const { servicesKitCrud, servicesKitList } = useServicesContext();
const isMobile = useIsMobile();
const onChange = (kit: ServicesKitSchema) => {
modals.openContextModal({
modal: "servicesKitEditorModal",
title: "Редактирование набора услуг",
withCloseButton: false,
innerProps: {
entity: kit,
onChange: value => servicesKitCrud.onUpdate(kit.id, value),
isEditing: true,
},
});
};
const columns = useServicesKitsTableColumns({
onChange,
onDelete: servicesKitCrud.onDelete,
});
return (
<BaseTable
records={servicesKitList.servicesKits}
columns={columns}
groups={undefined}
withTableBorder
verticalSpacing={"xs"}
mx={isMobile ? "xs" : 0}
/>
);
};
export default ServicesKitsTable;

View File

@ -0,0 +1,68 @@
import { useMemo } from "react";
import { IconEdit, IconTrash } from "@tabler/icons-react";
import { DataTableColumn } from "mantine-datatable";
import { Flex } from "@mantine/core";
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
import useIsMobile from "@/hooks/utils/useIsMobile";
import { ServicesKitSchema } from "@/lib/client";
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
type Props = {
onChange: (kit: ServicesKitSchema) => void;
onDelete: (kit: ServicesKitSchema) => void;
};
const useServicesKitsTableColumns = ({ onDelete, onChange }: Props) => {
const isMobile = useIsMobile();
return useMemo(
() =>
[
{
accessor: "actions",
title: "Действия",
sortable: false,
textAlign: "center",
width: "0%",
render: kit => (
<Flex gap={isMobile ? "xs" : "md"}>
<ActionIconWithTip
onClick={() => onChange(kit)}
tipLabel={"Редактировать"}>
<IconEdit />
</ActionIconWithTip>
<ActionIconWithTip
color={"red"}
onClick={() => onDelete(kit)}
tipLabel={"Удалить"}>
<IconTrash />
</ActionIconWithTip>
</Flex>
),
},
{
accessor: "name",
title: "Название",
width: "60%",
},
{
title: "Кол-во услуг",
accessor: "services",
render: kit => kit.services.length,
width: "20%",
},
{
title: "Тип набора",
accessor: "serviceType",
render: kit =>
kit.serviceType === ServiceType.DEAL_SERVICE
? "Для сделок"
: "Для товаров",
width: "20%",
},
] as DataTableColumn<ServicesKitSchema>[],
[]
);
};
export default useServicesKitsTableColumns;

View File

@ -0,0 +1,24 @@
"use client";
import { FC } from "react";
import ObjectMultiSelect, {
ObjectMultiSelectProps,
} from "@/components/selects/ObjectMultiSelect/ObjectMultiSelect";
import { ServiceSchema } from "@/lib/client";
import useServicesList from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServicesList";
type Props = Omit<ObjectMultiSelectProps<ServiceSchema>, "data">;
const ServicesMultiselect: FC<Props> = (props: Props) => {
const { services } = useServicesList();
return (
<ObjectMultiSelect
data={services}
searchable
{...props}
/>
);
};
export default ServicesMultiselect;

View File

@ -0,0 +1,45 @@
"use client";
import makeContext from "@/lib/contextFactory/contextFactory";
import {
ServicesCrud,
useServicesCrud,
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServicesCrud";
import {
ServicesKitsCrud,
useServicesKitsCrud,
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/cruds/useServicesKitsCrud";
import useServicesKitsList, {
ServicesKitsList,
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServicesKitsList";
import useServicesList, {
ServicesList,
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/hooks/lists/useServicesList";
type ServicesContextState = {
servicesList: ServicesList;
servicesCrud: ServicesCrud;
servicesKitList: ServicesKitsList;
servicesKitCrud: ServicesKitsCrud;
};
const useFulfillmentBaseContextState = (): ServicesContextState => {
const servicesList = useServicesList();
const servicesCrud = useServicesCrud(servicesList);
const servicesKitList = useServicesKitsList();
const servicesKitCrud = useServicesKitsCrud(servicesKitList);
return {
servicesList,
servicesCrud,
servicesKitList,
servicesKitCrud,
};
};
export const [ServicesContextProvider, useServicesContext] =
makeContext<ServicesContextState>(
useFulfillmentBaseContextState,
"Services"
);

View File

@ -0,0 +1,70 @@
"use client";
import { TextInput } from "@mantine/core";
import { useForm } from "@mantine/form";
import { ContextModalProps } from "@mantine/modals";
import ServicesMultiselect from "@/app/services/components/shared/ServicesMultiselect/ServicesMultiselect";
import ServiceTypeSegmentedControl from "@/app/services/components/shared/ServiceTypeSegmentedControl/ServiceTypeSegmentedControl";
import { ServicesKitSchema } from "@/lib/client";
import BaseFormModal, {
CreateEditFormProps,
} from "@/modals/base/BaseFormModal/BaseFormModal";
import { ServiceType } from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/types/service";
type Props = CreateEditFormProps<ServicesKitSchema>;
const ServicesKitEditorModal = ({
context,
id,
innerProps,
}: ContextModalProps<Props>) => {
const initialValues: Partial<ServicesKitSchema> = innerProps.isEditing
? innerProps.entity
: {
name: "",
serviceType: ServiceType.DEAL_SERVICE,
services: [],
};
const form = useForm<Partial<ServicesKitSchema>>({
initialValues,
validate: {
name: name => !name && "Введите название",
services: services =>
(!services || services.length === 0) && "Выберите услуги",
},
});
return (
<BaseFormModal
{...innerProps}
form={form}
closeOnSubmit
onClose={() => context.closeContextModal(id)}>
<TextInput
label={"Название"}
placeholder={"Введите название набора услуг"}
{...form.getInputProps("name")}
/>
<ServiceTypeSegmentedControl
value={form.values.serviceType?.toString()}
onChange={tab => {
form.setFieldValue("serviceType", Number(tab));
form.setFieldValue("services", []);
}}
mt={"xs"}
/>
<ServicesMultiselect
label={"Услуги"}
placeholder={"Выберите услуги"}
filterBy={service =>
service.serviceType === form.values.serviceType
}
groupBy={service => service.category.name}
{...form.getInputProps("services")}
/>
</BaseFormModal>
);
};
export default ServicesKitEditorModal;

View File

@ -0,0 +1 @@
export { default as ServicesKitEditorModal } from "@/app/services/modals/ServicesKitEditorModal";

22
src/app/services/page.tsx Normal file
View File

@ -0,0 +1,22 @@
import { Suspense } from "react";
import { Center, Loader } from "@mantine/core";
import PageBody from "@/app/services/components/shared/PageBody/PageBody";
import { ServicesContextProvider } from "@/app/services/contexts/ServicesContext";
import PageContainer from "@/components/layout/PageContainer/PageContainer";
export default async function ServicesPage() {
return (
<Suspense
fallback={
<Center h="50vh">
<Loader size="lg" />
</Center>
}>
<ServicesContextProvider>
<PageContainer>
<PageBody />
</PageContainer>
</ServicesContextProvider>
</Suspense>
);
}

View File

@ -1,4 +1,6 @@
.container { .container {
height: var(--mobile-footer-height);
@mixin light { @mixin light {
border-top: solid gray 2px; border-top: solid gray 2px;
} }
@ -9,7 +11,6 @@
.link { .link {
width: 100%; width: 100%;
height: rem(50px);
border-radius: var(--mantine-radius-md); border-radius: var(--mantine-radius-md);
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -1,4 +1,4 @@
import { IconCircleDotted, IconLayoutKanban } from "@tabler/icons-react"; import { IconColumns, IconLayoutKanban } from "@tabler/icons-react";
import { Box, Flex } from "@mantine/core"; import { Box, Flex } from "@mantine/core";
import PageBlock from "@/components/layout/PageBlock/PageBlock"; import PageBlock from "@/components/layout/PageBlock/PageBlock";
import { ColorSchemeToggle } from "@/components/ui/ColorSchemeToggle/ColorSchemeToggle"; import { ColorSchemeToggle } from "@/components/ui/ColorSchemeToggle/ColorSchemeToggle";
@ -13,9 +13,9 @@ const linksData = [
href: "/deals", href: "/deals",
}, },
{ {
icon: IconCircleDotted, icon: IconColumns,
label: "Назад", label: "Услуги",
href: "/oiiai", href: "/services",
}, },
]; ];

View File

@ -20,6 +20,10 @@
.container-full-height { .container-full-height {
height: var(--page-height); height: var(--page-height);
@media (max-width: 48em) {
height: var(--mobile-page-height);
}
} }
.container-no-border-radius { .container-no-border-radius {
@ -28,8 +32,8 @@
.container-full-screen-mobile { .container-full-screen-mobile {
@media (max-width: 48em) { @media (max-width: 48em) {
min-height: 100vh; min-height: var(--mobile-page-height);
height: 100vh; height: var(--mobile-page-height);
width: 100vw; width: 100vw;
border-radius: 0 !important; border-radius: 0 !important;
position: fixed; position: fixed;

View File

@ -93,7 +93,13 @@ const ObjectMultiSelect = <T,>(props: ObjectMultiSelectProps<T>) => {
props.onChange(internalValue); props.onChange(internalValue);
}, [internalValue]); }, [internalValue]);
const restProps = omit(props, "getValueFn", "getLabelFn", "filterBy"); const restProps = omit(
props,
"getValueFn",
"getLabelFn",
"filterBy",
"groupBy"
);
return ( return (
<MultiSelect <MultiSelect

View File

@ -5,6 +5,7 @@ import {
PolymorphicComponentProps, PolymorphicComponentProps,
Tooltip, Tooltip,
} from "@mantine/core"; } from "@mantine/core";
import useIsMobile from "@/hooks/utils/useIsMobile";
import style from "./ActionIconWithTip.module.css"; import style from "./ActionIconWithTip.module.css";
type Props = PolymorphicComponentProps<"button", ActionIconProps> & { type Props = PolymorphicComponentProps<"button", ActionIconProps> & {
@ -15,20 +16,24 @@ const ActionIconWithTip: FC<PropsWithChildren<Props>> = ({
children, children,
tipLabel, tipLabel,
...props ...props
}) => ( }) => {
const isMobile = useIsMobile();
return (
<Tooltip <Tooltip
label={tipLabel} label={tipLabel}
hidden={!tipLabel} hidden={!tipLabel}
h={"max-content"} h={"max-content"}
w={"max-content"}> w={"max-content"}>
<ActionIcon <ActionIcon
variant={"default"} variant={isMobile ? "subtle" : "default"}
radius={"lg"} radius={"lg"}
className={style.container} className={style.container}
{...props}> {...props}>
{children} {children}
</ActionIcon> </ActionIcon>
</Tooltip> </Tooltip>
); );
};
export default ActionIconWithTip; export default ActionIconWithTip;

View File

@ -1,4 +1,13 @@
.table-bg {
@mixin light {
background-color: white;
}
@mixin dark {
background-color: var(--mantine-color-dark-8);
}
}
.table-border { .table-border {
border-width: 1px; border-width: 1px;
border-radius: var(--mantine-radius-lg); border-radius: var(--mantine-radius-lg);

View File

@ -9,7 +9,12 @@ function BaseTable<T>(props: DataTableProps<T>) {
withRowBorders withRowBorders
striped={false} striped={false}
verticalAlign={"center"} verticalAlign={"center"}
backgroundColor={"transparent"} classNames={{
root: styles["table-bg"],
table: styles["table-bg"],
header: styles["table-bg"],
footer: styles["table-bg"],
}}
className={classNames( className={classNames(
props.withTableBorder && styles["table-border"] props.withTableBorder && styles["table-border"]
)} )}

View File

@ -90,6 +90,10 @@ export type BuiltInModuleTabSchema = {
* Id * Id
*/ */
id: number; id: number;
/**
* Key
*/
key: string;
/** /**
* Label * Label
*/ */
@ -468,9 +472,9 @@ export type CreateServicesKitSchema = {
*/ */
serviceType: number; serviceType: number;
/** /**
* Servicesids * Services
*/ */
servicesIds: Array<number>; services: Array<ServiceSchema>;
}; };
/** /**
@ -1487,9 +1491,9 @@ export type UpdateServicesKitSchema = {
*/ */
serviceType: number; serviceType: number;
/** /**
* Servicesids * Services
*/ */
servicesIds: Array<number>; services: Array<ServiceSchema>;
}; };
/** /**

View File

@ -17,6 +17,7 @@ export const zBoardSchema = z.object({
*/ */
export const zBuiltInModuleTabSchema = z.object({ export const zBuiltInModuleTabSchema = z.object({
id: z.int(), id: z.int(),
key: z.string(),
label: z.string(), label: z.string(),
iconName: z.string(), iconName: z.string(),
device: z.string(), device: z.string(),
@ -385,7 +386,7 @@ export const zCreateServiceResponse = z.object({
export const zCreateServicesKitSchema = z.object({ export const zCreateServicesKitSchema = z.object({
name: z.string(), name: z.string(),
serviceType: z.int(), serviceType: z.int(),
servicesIds: z.array(z.int()), services: z.array(zServiceSchema),
}); });
/** /**
@ -878,7 +879,7 @@ export const zUpdateServiceResponse = z.object({
export const zUpdateServicesKitSchema = z.object({ export const zUpdateServicesKitSchema = z.object({
name: z.string(), name: z.string(),
serviceType: z.int(), serviceType: z.int(),
servicesIds: z.array(z.int()), services: z.array(zServiceSchema),
}); });
/** /**

View File

@ -1,6 +1,7 @@
import DealsBoardFiltersModal from "@/app/deals/modals/DealsBoardFiltersModal/DealsBoardFiltersModal"; import DealsBoardFiltersModal from "@/app/deals/modals/DealsBoardFiltersModal/DealsBoardFiltersModal";
import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal"; import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal";
import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal"; import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal";
import { ServicesKitEditorModal } from "@/app/services/modals";
import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal"; import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal";
import { import {
DealProductEditorModal, DealProductEditorModal,
@ -22,4 +23,5 @@ export const modals = {
productServiceEditorModal: ProductServiceEditorModal, productServiceEditorModal: ProductServiceEditorModal,
duplicateServicesModal: DuplicateServicesModal, duplicateServicesModal: DuplicateServicesModal,
servicesKitSelectModal: ServicesKitSelectModal, servicesKitSelectModal: ServicesKitSelectModal,
servicesKitEditorModal: ServicesKitEditorModal,
}; };

View File

@ -0,0 +1,51 @@
import { useCrudOperations } from "@/hooks/cruds/baseCrud";
import {
CreateServicesKitSchema,
ServicesKitSchema,
UpdateServicesKitSchema,
} from "@/lib/client";
import {
createServicesKitMutation,
deleteServicesKitMutation,
updateServicesKitMutation,
} from "@/lib/client/@tanstack/react-query.gen";
type Props = {
queryKey: any[];
};
export type ServicesKitsCrud = {
onCreate: (data: Partial<CreateServicesKitSchema>) => void;
onUpdate: (
servicesKitId: number,
servicesKit: UpdateServicesKitSchema
) => void;
onDelete: (servicesKit: ServicesKitSchema, onSuccess?: () => void) => void;
};
export const useServicesKitsCrud = ({ queryKey }: Props): ServicesKitsCrud => {
return useCrudOperations<
ServicesKitSchema,
UpdateServicesKitSchema,
CreateServicesKitSchema
>({
key: "getServicesKits",
queryKey,
mutations: {
create: createServicesKitMutation(),
update: updateServicesKitMutation(),
delete: deleteServicesKitMutation(),
},
getCreateEntity: data => ({
name: data.name!,
serviceType: data.serviceType!,
services: data.services!,
}),
getUpdateEntity: (old, update) => ({
...old,
name: update.name ?? old.name,
serviceType: update.serviceType ?? old.serviceType,
}),
getDeleteConfirmTitle: () => "Удаление набора услуг",
});
};

View File

@ -5,7 +5,15 @@ import {
getServicesKitsQueryKey, getServicesKitsQueryKey,
} from "@/lib/client/@tanstack/react-query.gen"; } from "@/lib/client/@tanstack/react-query.gen";
const useServicesKitsList = () => { export type ServicesKitsList = {
servicesKits: ServicesKitSchema[];
setServicesKits: (servicesKits: ServicesKitSchema[]) => void;
refetch: () => void;
queryKey: any[];
isLoading: boolean;
};
const useServicesKitsList = (): ServicesKitsList => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data, refetch, isLoading } = useQuery(getServicesKitsOptions()); const { data, refetch, isLoading } = useQuery(getServicesKitsOptions());

View File

@ -5,8 +5,15 @@ import {
getServicesQueryKey, getServicesQueryKey,
} from "@/lib/client/@tanstack/react-query.gen"; } from "@/lib/client/@tanstack/react-query.gen";
export type ServicesList = {
services: ServiceSchema[];
setServices: (services: ServiceSchema[]) => void;
refetch: () => void;
queryKey: any[];
isLoading: boolean;
};
const useServicesList = () => { const useServicesList = (): ServicesList => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { data, refetch, isLoading } = useQuery(getServicesOptions()); const { data, refetch, isLoading } = useQuery(getServicesOptions());

View File

@ -62,5 +62,15 @@ export const theme = createTheme({
decimalSeparator: ",", decimalSeparator: ",",
}, },
}, },
MultiSelect: {
defaultProps: {
radius,
},
},
SegmentedControl: {
defaultProps: {
radius,
},
},
}, },
}); });