feat: client tab in deal editor

This commit is contained in:
2025-10-05 12:05:23 +04:00
parent d14920df7d
commit 0fcf086861
21 changed files with 511 additions and 35 deletions

View File

@ -2,9 +2,15 @@ import { FC } from "react";
import { IconCheck, IconX } from "@tabler/icons-react";
import { Button, Group, Stack, TextInput } from "@mantine/core";
import { useForm } from "@mantine/form";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import { ClientSchema } from "@/lib/client";
import ClientSelect from "@/modules/dealModularEditorTabs/Clients/shared/components/ClientSelect";
import { ModuleNames } from "@/modules/modules";
export type CreateDealForm = {
name: string;
client?: ClientSchema;
clientId?: number;
};
type Props = {
@ -13,25 +19,42 @@ type Props = {
};
const CreateCardForm: FC<Props> = ({ onSubmit, onCancel }) => {
const { modulesSet } = useProjectsContext();
const form = useForm<CreateDealForm>({
initialValues: {
name: "",
},
validate: {
name: value => !value && "Введите название",
client: client =>
modulesSet.has(ModuleNames.CLIENTS) &&
!client &&
"Выберите клиента",
},
});
return (
<form onSubmit={form.onSubmit(values => {
onSubmit(values);
form.reset();
})}>
<form
onSubmit={form.onSubmit(values => {
onSubmit(values);
form.reset();
})}>
<Stack>
<TextInput
placeholder={"Название"}
{...form.getInputProps("name")}
/>
{modulesSet.has(ModuleNames.CLIENTS) && (
<ClientSelect
placeholder={"Клиент"}
{...form.getInputProps("client")}
onChange={client => {
form.setFieldValue("client", client);
form.setFieldValue("clientId", client?.id);
}}
/>
)}
<Group wrap={"nowrap"}>
<Button
variant={"default"}

View File

@ -3,6 +3,7 @@ import { useDealsContext } from "@/app/deals/contexts/DealsContext";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import { useDrawersContext } from "@/drawers/DrawersContext";
import { DealSchema } from "@/lib/client";
import { ModuleNames } from "@/modules/modules";
import styles from "./DealCard.module.css";
type Props = {
@ -10,7 +11,7 @@ type Props = {
};
const DealCard = ({ deal }: Props) => {
const { selectedProject } = useProjectsContext();
const { selectedProject, modulesSet } = useProjectsContext();
const { dealsCrud } = useDealsContext();
const { openDrawer } = useDrawersContext();
@ -47,6 +48,9 @@ const DealCard = ({ deal }: Props) => {
</Group>
<Stack className={styles["deal-data"]}>
<Stack gap={0}>
{modulesSet.has(ModuleNames.CLIENTS) && (
<Text>{deal.client?.name}</Text>
)}
<Text>Wb электросталь</Text>
<Text>19 000 руб.</Text>
<Text>130 тов.</Text>

View File

@ -1,6 +1,6 @@
"use client";
import React, { useState } from "react";
import React, { useMemo, useState } from "react";
import { ProjectsCrud, useProjectsCrud } from "@/hooks/cruds/useProjectsCrud";
import useProjectsList from "@/hooks/lists/useProjectsList";
import { ProjectSchema } from "@/lib/client";
@ -12,6 +12,7 @@ type ProjectsContextState = {
refetchProjects: () => void;
projects: ProjectSchema[];
projectsCrud: ProjectsCrud;
modulesSet: Set<string>;
};
const useProjectsContextState = (): ProjectsContextState => {
@ -20,8 +21,16 @@ const useProjectsContextState = (): ProjectsContextState => {
const [selectedProjectId, setSelectedProjectId] = useState<number | null>(
null
);
const selectedProject =
projects.find(project => project.id === selectedProjectId) ?? null;
const selectedProject = useMemo(
() =>
projects.find(project => project.id === selectedProjectId) ?? null,
[projects, selectedProjectId]
);
const modulesSet = useMemo(
() => new Set(selectedProject?.builtInModules.map(m => m.key)),
[selectedProject]
);
if (selectedProject === null && projects.length > 0) {
setSelectedProjectId(projects[0].id);
@ -35,6 +44,7 @@ const useProjectsContextState = (): ProjectsContextState => {
refetchProjects,
setSelectedProjectId,
projectsCrud,
modulesSet,
};
};

View File

@ -1,9 +1,10 @@
import React, { FC } from "react";
import { Flex, Stack, TextInput } from "@mantine/core";
import { Stack, TextInput } from "@mantine/core";
import { useForm } from "@mantine/form";
import Footer from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/components/Footer";
import BoardSelect from "@/components/selects/BoardSelect/BoardSelect";
import StatusSelect from "@/components/selects/StatusSelect/StatusSelect";
import FormFlexRow from "@/components/ui/FormFlexRow/FormFlexRow";
import { BoardSchema, DealSchema, StatusSchema } from "@/lib/client";
import { utcDateTimeToLocalString } from "@/utils/datetime";
@ -40,10 +41,7 @@ const GeneralTab: FC<Props> = ({ value, onDelete, onChange }) => {
return (
<form onSubmit={form.onSubmit(onSubmit)}>
<Stack p={"md"}>
<Flex
gap={"md"}
w={"100%"}
direction={{ base: "column", sm: "row" }}>
<FormFlexRow>
<TextInput
label={"Название"}
{...form.getInputProps("name")}
@ -55,11 +53,8 @@ const GeneralTab: FC<Props> = ({ value, onDelete, onChange }) => {
readOnly
flex={1}
/>
</Flex>
<Flex
gap={"md"}
w={"100%"}
direction={{ base: "column", sm: "row" }}>
</FormFlexRow>
<FormFlexRow>
<BoardSelect
label={"Доска"}
{...form.getInputProps("board")}
@ -76,7 +71,7 @@ const GeneralTab: FC<Props> = ({ value, onDelete, onChange }) => {
boardId={form.values.board?.id}
flex={1}
/>
</Flex>
</FormFlexRow>
<Footer
form={form}
onDelete={() => onDelete(value)}