feat: board and status selects in deal editor
This commit is contained in:
@ -3,21 +3,25 @@ import { IconEdit } from "@tabler/icons-react";
|
|||||||
import { DataTableColumn } from "mantine-datatable";
|
import { DataTableColumn } from "mantine-datatable";
|
||||||
import { ActionIcon, Tooltip } from "@mantine/core";
|
import { ActionIcon, Tooltip } from "@mantine/core";
|
||||||
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
||||||
|
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
|
||||||
import { useDrawersContext } from "@/drawers/DrawersContext";
|
import { useDrawersContext } from "@/drawers/DrawersContext";
|
||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema } from "@/lib/client";
|
||||||
import { utcDateTimeToLocalString } from "@/utils/datetime";
|
import { utcDateTimeToLocalString } from "@/utils/datetime";
|
||||||
|
|
||||||
const useDealsTableColumns = () => {
|
const useDealsTableColumns = () => {
|
||||||
|
const { selectedProject } = useProjectsContext();
|
||||||
const { dealsCrud } = useDealsContext();
|
const { dealsCrud } = useDealsContext();
|
||||||
const { openDrawer } = useDrawersContext();
|
const { openDrawer } = useDrawersContext();
|
||||||
|
|
||||||
const onEditDeal = useCallback(
|
const onEditDeal = useCallback(
|
||||||
(deal: DealSchema) => {
|
(deal: DealSchema) => {
|
||||||
|
if (!selectedProject) return;
|
||||||
openDrawer({
|
openDrawer({
|
||||||
key: "dealEditorDrawer",
|
key: "dealEditorDrawer",
|
||||||
props: {
|
props: {
|
||||||
deal,
|
deal,
|
||||||
dealsCrud,
|
dealsCrud,
|
||||||
|
project: selectedProject,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Box, Card, Group, Pill, Stack, Text } from "@mantine/core";
|
import { Box, Card, Group, Pill, Stack, Text } from "@mantine/core";
|
||||||
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
||||||
|
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
|
||||||
import { useDrawersContext } from "@/drawers/DrawersContext";
|
import { useDrawersContext } from "@/drawers/DrawersContext";
|
||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema } from "@/lib/client";
|
||||||
import styles from "./DealCard.module.css";
|
import styles from "./DealCard.module.css";
|
||||||
@ -9,11 +10,16 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DealCard = ({ deal }: Props) => {
|
const DealCard = ({ deal }: Props) => {
|
||||||
|
const { selectedProject } = useProjectsContext();
|
||||||
const { dealsCrud } = useDealsContext();
|
const { dealsCrud } = useDealsContext();
|
||||||
const { openDrawer } = useDrawersContext();
|
const { openDrawer } = useDrawersContext();
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
openDrawer({ key: "dealEditorDrawer", props: { deal, dealsCrud } });
|
if (!selectedProject) return;
|
||||||
|
openDrawer({
|
||||||
|
key: "dealEditorDrawer",
|
||||||
|
props: { project: selectedProject, deal, dealsCrud },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -22,7 +28,9 @@ const DealCard = ({ deal }: Props) => {
|
|||||||
className={styles.container}>
|
className={styles.container}>
|
||||||
<Group
|
<Group
|
||||||
justify={"space-between"}
|
justify={"space-between"}
|
||||||
ml={"xs"}
|
wrap={"nowrap"}
|
||||||
|
pl={"xs"}
|
||||||
|
gap={"xs"}
|
||||||
align={"start"}>
|
align={"start"}>
|
||||||
<Text
|
<Text
|
||||||
c={"dodgerblue"}
|
c={"dodgerblue"}
|
||||||
@ -30,7 +38,7 @@ const DealCard = ({ deal }: Props) => {
|
|||||||
{deal.name}
|
{deal.name}
|
||||||
</Text>
|
</Text>
|
||||||
<Box className={styles["deal-id"]}>
|
<Box className={styles["deal-id"]}>
|
||||||
<Text>ID: {deal.id}</Text>
|
<Text style={{ textWrap: "nowrap" }}>ID: {deal.id}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Group>
|
</Group>
|
||||||
<Stack className={styles["deal-data"]}>
|
<Stack className={styles["deal-data"]}>
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const Funnel: FC = () => {
|
|||||||
getContainerId={(status: StatusSchema) => `${status.id}-status`}
|
getContainerId={(status: StatusSchema) => `${status.id}-status`}
|
||||||
getItemsByContainer={(status: StatusSchema, items: DealSchema[]) =>
|
getItemsByContainer={(status: StatusSchema, items: DealSchema[]) =>
|
||||||
sortByLexorank(
|
sortByLexorank(
|
||||||
items.filter(deal => deal.statusId === status.id)
|
items.filter(deal => deal.status.id === status.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
renderContainer={(
|
renderContainer={(
|
||||||
|
|||||||
@ -6,9 +6,10 @@ import DealEditorBody from "@/app/deals/drawers/DealEditorDrawer/components/Deal
|
|||||||
import { DrawerProps } from "@/drawers/types";
|
import { DrawerProps } from "@/drawers/types";
|
||||||
import { DealsCrud } from "@/hooks/cruds/useDealsCrud";
|
import { DealsCrud } from "@/hooks/cruds/useDealsCrud";
|
||||||
import useIsMobile from "@/hooks/utils/useIsMobile";
|
import useIsMobile from "@/hooks/utils/useIsMobile";
|
||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema, ProjectSchema } from "@/lib/client";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
project: ProjectSchema;
|
||||||
deal: DealSchema;
|
deal: DealSchema;
|
||||||
dealsCrud: DealsCrud;
|
dealsCrud: DealsCrud;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { IconCircleDotted, IconEdit } from "@tabler/icons-react";
|
import { IconCircleDotted, IconEdit } from "@tabler/icons-react";
|
||||||
import { Tabs, Text } from "@mantine/core";
|
import { Tabs, Text } from "@mantine/core";
|
||||||
import GeneralTab from "@/app/deals/drawers/DealEditorDrawer/components/GeneralTab";
|
import GeneralTab from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/GeneralTab";
|
||||||
import { DealsCrud } from "@/hooks/cruds/useDealsCrud";
|
import { DealsCrud } from "@/hooks/cruds/useDealsCrud";
|
||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema, ProjectSchema } from "@/lib/client";
|
||||||
import styles from "../DealEditorDrawer.module.css";
|
import styles from "../DealEditorDrawer.module.css";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
project: ProjectSchema;
|
||||||
dealsCrud: DealsCrud;
|
dealsCrud: DealsCrud;
|
||||||
deal: DealSchema;
|
deal: DealSchema;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DealEditorBody: FC<Props> = ({ dealsCrud, deal, onClose }) => {
|
const DealEditorBody: FC<Props> = ({ project, dealsCrud, deal, onClose }) => {
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="general"
|
defaultValue="general"
|
||||||
@ -32,6 +33,7 @@ const DealEditorBody: FC<Props> = ({ dealsCrud, deal, onClose }) => {
|
|||||||
|
|
||||||
<Tabs.Panel value="general">
|
<Tabs.Panel value="general">
|
||||||
<GeneralTab
|
<GeneralTab
|
||||||
|
project={project}
|
||||||
dealsCrud={dealsCrud}
|
dealsCrud={dealsCrud}
|
||||||
deal={deal}
|
deal={deal}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
|
|||||||
@ -1,71 +0,0 @@
|
|||||||
import { FC, useState } from "react";
|
|
||||||
import { isEqual } from "lodash";
|
|
||||||
import { Button, Group, Stack, Text, TextInput } from "@mantine/core";
|
|
||||||
import { useForm } from "@mantine/form";
|
|
||||||
import { DealsCrud } from "@/hooks/cruds/useDealsCrud";
|
|
||||||
import { DealSchema } from "@/lib/client";
|
|
||||||
import { utcDateTimeToLocalString } from "@/utils/datetime";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
dealsCrud: DealsCrud;
|
|
||||||
deal: DealSchema;
|
|
||||||
onClose: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const GeneralTab: FC<Props> = ({ deal, dealsCrud, onClose }) => {
|
|
||||||
const [initialValues, setInitialValues] = useState(deal);
|
|
||||||
const form = useForm<DealSchema>({
|
|
||||||
initialValues,
|
|
||||||
validate: {
|
|
||||||
name: value => !value && "Введите название",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const onSubmit = (values: DealSchema) => {
|
|
||||||
dealsCrud.onUpdate(deal.id, values);
|
|
||||||
setInitialValues(values);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDelete = () => {
|
|
||||||
dealsCrud.onDelete(deal, onClose);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={form.onSubmit(onSubmit)}>
|
|
||||||
<Stack p={"md"}>
|
|
||||||
<TextInput
|
|
||||||
label={"Название"}
|
|
||||||
{...form.getInputProps("name")}
|
|
||||||
/>
|
|
||||||
<Text>Создано: {utcDateTimeToLocalString(deal.createdAt)}</Text>
|
|
||||||
<Group
|
|
||||||
justify={"space-between"}
|
|
||||||
wrap={"nowrap"}>
|
|
||||||
<Group wrap={"nowrap"}>
|
|
||||||
<Button
|
|
||||||
type={"submit"}
|
|
||||||
disabled={isEqual(form.values, initialValues)}
|
|
||||||
variant={"filled"}>
|
|
||||||
Сохранить
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type={"reset"}
|
|
||||||
onClick={() => form.reset()}
|
|
||||||
disabled={isEqual(form.values, initialValues)}
|
|
||||||
variant={"default"}>
|
|
||||||
Отменить
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
<Button
|
|
||||||
onClick={onDelete}
|
|
||||||
color={"red"}
|
|
||||||
variant={"outline"}>
|
|
||||||
Удалить
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GeneralTab;
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
import { Button, Group } from "@mantine/core";
|
||||||
|
import { UseFormReturnType } from "@mantine/form";
|
||||||
|
import { DealSchema } from "@/lib/client";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
form: UseFormReturnType<Partial<DealSchema>>;
|
||||||
|
initialValues: Partial<DealSchema>;
|
||||||
|
onDelete: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Footer: FC<Props> = ({ form, initialValues, onDelete }) => {
|
||||||
|
return (
|
||||||
|
<Group
|
||||||
|
justify={"space-between"}
|
||||||
|
wrap={"nowrap"}>
|
||||||
|
<Group wrap={"nowrap"}>
|
||||||
|
<Button
|
||||||
|
type={"submit"}
|
||||||
|
disabled={isEqual(form.values, initialValues)}
|
||||||
|
variant={"filled"}>
|
||||||
|
Сохранить
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type={"reset"}
|
||||||
|
onClick={() => form.reset()}
|
||||||
|
disabled={isEqual(form.values, initialValues)}
|
||||||
|
variant={"default"}>
|
||||||
|
Отменить
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
<Button
|
||||||
|
onClick={onDelete}
|
||||||
|
color={"red"}
|
||||||
|
variant={"outline"}>
|
||||||
|
Удалить
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
import { FC, useState } from "react";
|
||||||
|
import { Stack, Text, TextInput } from "@mantine/core";
|
||||||
|
import { useForm } from "@mantine/form";
|
||||||
|
import Footer from "@/app/deals/drawers/DealEditorDrawer/tabs/GeneralTab/Footer";
|
||||||
|
import BoardSelect from "@/components/selects/BoardSelect/BoardSelect";
|
||||||
|
import StatusSelect from "@/components/selects/StatusSelect/StatusSelect";
|
||||||
|
import { DealsCrud } from "@/hooks/cruds/useDealsCrud";
|
||||||
|
import { DealSchema, ProjectSchema } from "@/lib/client";
|
||||||
|
import { utcDateTimeToLocalString } from "@/utils/datetime";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
project: ProjectSchema;
|
||||||
|
dealsCrud: DealsCrud;
|
||||||
|
deal: DealSchema;
|
||||||
|
onClose: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const GeneralTab: FC<Props> = ({ project, deal, dealsCrud, onClose }) => {
|
||||||
|
const [initialValues, setInitialValues] =
|
||||||
|
useState<Partial<DealSchema>>(deal);
|
||||||
|
const form = useForm<Partial<DealSchema>>({
|
||||||
|
initialValues,
|
||||||
|
validate: {
|
||||||
|
name: value => !value && "Введите название",
|
||||||
|
board: value => !value && "Выберите доску",
|
||||||
|
status: value => !value && "Выберите статус",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: Partial<DealSchema>) => {
|
||||||
|
dealsCrud.onUpdate(deal.id, {
|
||||||
|
...values,
|
||||||
|
boardId: values.board?.id,
|
||||||
|
statusId: values.status?.id,
|
||||||
|
});
|
||||||
|
setInitialValues(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDelete = () => {
|
||||||
|
dealsCrud.onDelete(deal, onClose);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={form.onSubmit(onSubmit)}>
|
||||||
|
<Stack p={"md"}>
|
||||||
|
<TextInput
|
||||||
|
label={"Название"}
|
||||||
|
{...form.getInputProps("name")}
|
||||||
|
/>
|
||||||
|
<Text>Создано: {utcDateTimeToLocalString(deal.createdAt)}</Text>
|
||||||
|
<BoardSelect
|
||||||
|
label={"Доска"}
|
||||||
|
{...form.getInputProps("board")}
|
||||||
|
projectId={project?.id}
|
||||||
|
/>
|
||||||
|
<StatusSelect
|
||||||
|
label={"Статус"}
|
||||||
|
{...form.getInputProps("status")}
|
||||||
|
boardId={form.values.board?.id}
|
||||||
|
/>
|
||||||
|
<Footer
|
||||||
|
form={form}
|
||||||
|
initialValues={initialValues}
|
||||||
|
onDelete={onDelete}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GeneralTab;
|
||||||
@ -41,7 +41,11 @@ const useDealsAndStatusesDnd = (): ReturnType => {
|
|||||||
const getStatusByDealId = (dealId: number) => {
|
const getStatusByDealId = (dealId: number) => {
|
||||||
const deal = deals.find(deal => deal.id === dealId);
|
const deal = deals.find(deal => deal.id === dealId);
|
||||||
if (!deal) return;
|
if (!deal) return;
|
||||||
return statuses.find(status => status.id === deal.statusId);
|
return statuses.find(status => status.id === deal.status.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusById = (statusId: number) => {
|
||||||
|
return statuses.find(status => status.id === statusId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const swipeSliderDuringDrag = (activeId: number, over: Over) => {
|
const swipeSliderDuringDrag = (activeId: number, over: Over) => {
|
||||||
@ -105,19 +109,19 @@ const useDealsAndStatusesDnd = (): ReturnType => {
|
|||||||
const activeStatusId = getStatusByDealId(activeDealId)?.id;
|
const activeStatusId = getStatusByDealId(activeDealId)?.id;
|
||||||
if (!activeStatusId) return;
|
if (!activeStatusId) return;
|
||||||
|
|
||||||
const { overStatusId, newLexorank } = getDropTarget(
|
const { overStatus, newLexorank } = getDropTarget(
|
||||||
over.id,
|
over.id,
|
||||||
activeDealId,
|
activeDealId,
|
||||||
activeStatusId
|
activeStatusId
|
||||||
);
|
);
|
||||||
if (!overStatusId) return;
|
if (!overStatus) return;
|
||||||
|
|
||||||
debouncedSetDeals(
|
debouncedSetDeals(
|
||||||
deals.map(deal =>
|
deals.map(deal =>
|
||||||
deal.id === activeDealId
|
deal.id === activeDealId
|
||||||
? {
|
? {
|
||||||
...deal,
|
...deal,
|
||||||
statusId: overStatusId,
|
status: overStatus,
|
||||||
lexorank: newLexorank || deal.lexorank,
|
lexorank: newLexorank || deal.lexorank,
|
||||||
}
|
}
|
||||||
: deal
|
: deal
|
||||||
@ -134,7 +138,7 @@ const useDealsAndStatusesDnd = (): ReturnType => {
|
|||||||
} else {
|
} else {
|
||||||
const deal = deals.find(deal => deal.id === over.id);
|
const deal = deals.find(deal => deal.id === over.id);
|
||||||
if (!deal) return;
|
if (!deal) return;
|
||||||
overStatusId = deal.statusId;
|
overStatusId = deal.status.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overStatusId || activeStatusId === overStatusId) return;
|
if (!overStatusId || activeStatusId === overStatusId) return;
|
||||||
@ -156,42 +160,42 @@ const useDealsAndStatusesDnd = (): ReturnType => {
|
|||||||
activeDealId: number,
|
activeDealId: number,
|
||||||
activeStatusId: number,
|
activeStatusId: number,
|
||||||
isOnDragEnd: boolean = false
|
isOnDragEnd: boolean = false
|
||||||
) => {
|
): { overStatus?: StatusSchema; newLexorank?: string } => {
|
||||||
if (typeof overId === "string") {
|
if (typeof overId === "string") {
|
||||||
return {
|
return {
|
||||||
overStatusId: getStatusId(overId),
|
overStatus: getStatusById(getStatusId(overId)),
|
||||||
newLexorank: undefined,
|
newLexorank: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const overDealId = Number(overId);
|
const overDealId = Number(overId);
|
||||||
const overStatusId = getStatusByDealId(overDealId)?.id;
|
const overStatus = getStatusByDealId(overDealId);
|
||||||
|
|
||||||
if (!overStatusId || (!isOnDragEnd && activeDealId === overDealId)) {
|
if (!overStatus || (!isOnDragEnd && activeDealId === overDealId)) {
|
||||||
return { overStatusId: undefined, newLexorank: undefined };
|
return { overStatus: undefined, newLexorank: undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusDeals = sortByLexorank(
|
const statusDeals = sortByLexorank(
|
||||||
deals.filter(deal => deal.statusId === overStatusId)
|
deals.filter(deal => deal.status.id === overStatus.id)
|
||||||
);
|
);
|
||||||
const overDealIndex = statusDeals.findIndex(
|
const overDealIndex = statusDeals.findIndex(
|
||||||
deal => deal.id === overDealId
|
deal => deal.id === overDealId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (activeStatusId === overStatusId) {
|
if (activeStatusId === overStatus.id) {
|
||||||
const newLexorank = getNewRankForSameStatus(
|
const newLexorank = getNewRankForSameStatus(
|
||||||
statusDeals,
|
statusDeals,
|
||||||
overDealIndex,
|
overDealIndex,
|
||||||
activeDealId
|
activeDealId
|
||||||
);
|
);
|
||||||
return { overStatusId, newLexorank };
|
return { overStatus, newLexorank };
|
||||||
}
|
}
|
||||||
|
|
||||||
const newLexorank = getNewRankForAnotherStatus(
|
const newLexorank = getNewRankForAnotherStatus(
|
||||||
statusDeals,
|
statusDeals,
|
||||||
overDealIndex
|
overDealIndex
|
||||||
);
|
);
|
||||||
return { overStatusId, newLexorank };
|
return { overStatus, newLexorank };
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDragEnd = ({ active, over }: DragOverEvent) => {
|
const handleDragEnd = ({ active, over }: DragOverEvent) => {
|
||||||
@ -215,9 +219,9 @@ const useDealsAndStatusesDnd = (): ReturnType => {
|
|||||||
if (typeof over.id === "string" && isStatusId(over.id)) {
|
if (typeof over.id === "string" && isStatusId(over.id)) {
|
||||||
overStatusId = getStatusId(over.id);
|
overStatusId = getStatusId(over.id);
|
||||||
} else {
|
} else {
|
||||||
const deal = deals.find(deal => deal.statusId === over.id);
|
const deal = deals.find(deal => deal.status.id === over.id);
|
||||||
if (!deal) return;
|
if (!deal) return;
|
||||||
overStatusId = deal.statusId;
|
overStatusId = deal.status.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overStatusId) return;
|
if (!overStatusId) return;
|
||||||
@ -237,15 +241,15 @@ const useDealsAndStatusesDnd = (): ReturnType => {
|
|||||||
const activeStatusId = getStatusByDealId(activeDealId)?.id;
|
const activeStatusId = getStatusByDealId(activeDealId)?.id;
|
||||||
if (!activeStatusId) return;
|
if (!activeStatusId) return;
|
||||||
|
|
||||||
const { overStatusId, newLexorank } = getDropTarget(
|
const { overStatus, newLexorank } = getDropTarget(
|
||||||
over.id,
|
over.id,
|
||||||
activeDealId,
|
activeDealId,
|
||||||
activeStatusId,
|
activeStatusId,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if (!overStatusId) return;
|
if (!overStatus) return;
|
||||||
|
|
||||||
onDealDragEnd(activeDealId, overStatusId, newLexorank);
|
onDealDragEnd(activeDealId, overStatus.id, newLexorank);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDealDragEnd = (
|
const onDealDragEnd = (
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { FC, useEffect } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import ObjectSelect, {
|
import ObjectSelect, {
|
||||||
ObjectSelectProps,
|
ObjectSelectProps,
|
||||||
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
} from "@/components/selects/ObjectSelect/ObjectSelect";
|
||||||
@ -15,12 +15,17 @@ type Props = Omit<
|
|||||||
};
|
};
|
||||||
|
|
||||||
const StatusSelect: FC<Props> = ({ boardId, ...props }) => {
|
const StatusSelect: FC<Props> = ({ boardId, ...props }) => {
|
||||||
|
const [isInitial, setIsInitial] = useState<boolean>(true);
|
||||||
const onClear = () => props.onChange(null);
|
const onClear = () => props.onChange(null);
|
||||||
|
|
||||||
const { statuses } = useStatusesList({ boardId });
|
const { statuses } = useStatusesList({ boardId });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!boardId) props.onChange(null);
|
if (isInitial) {
|
||||||
|
setIsInitial(false);
|
||||||
|
} else {
|
||||||
|
onClear();
|
||||||
|
}
|
||||||
}, [boardId]);
|
}, [boardId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export const useDealsCrud = ({
|
|||||||
if (!boardId || statuses.length === 0) return null;
|
if (!boardId || statuses.length === 0) return null;
|
||||||
const firstStatus = statuses[0];
|
const firstStatus = statuses[0];
|
||||||
const filteredDeals = deals.filter(
|
const filteredDeals = deals.filter(
|
||||||
d => d.statusId === firstStatus.id
|
d => d.status.id === firstStatus.id
|
||||||
);
|
);
|
||||||
let firstDeal: DealSchema | null = null;
|
let firstDeal: DealSchema | null = null;
|
||||||
if (filteredDeals.length > 0) {
|
if (filteredDeals.length > 0) {
|
||||||
@ -65,7 +65,12 @@ export const useDealsCrud = ({
|
|||||||
...old,
|
...old,
|
||||||
name: update.name ?? old.name,
|
name: update.name ?? old.name,
|
||||||
lexorank: update.lexorank ?? old.lexorank,
|
lexorank: update.lexorank ?? old.lexorank,
|
||||||
statusId: update.statusId ?? old.statusId,
|
status: update.statusId
|
||||||
|
? { ...old.status, id: update.statusId }
|
||||||
|
: old.status,
|
||||||
|
board: update.boardId
|
||||||
|
? { ...old.board, id: update.boardId }
|
||||||
|
: old.board,
|
||||||
}),
|
}),
|
||||||
getDeleteConfirmTitle: () => "Удаление сделки",
|
getDeleteConfirmTitle: () => "Удаление сделки",
|
||||||
});
|
});
|
||||||
|
|||||||
@ -174,14 +174,8 @@ export type DealSchema = {
|
|||||||
* Lexorank
|
* Lexorank
|
||||||
*/
|
*/
|
||||||
lexorank: string;
|
lexorank: string;
|
||||||
/**
|
status: StatusSchema;
|
||||||
* Statusid
|
board: BoardSchema;
|
||||||
*/
|
|
||||||
statusId: number;
|
|
||||||
/**
|
|
||||||
* Boardid
|
|
||||||
*/
|
|
||||||
boardId: number;
|
|
||||||
/**
|
/**
|
||||||
* Createdat
|
* Createdat
|
||||||
*/
|
*/
|
||||||
@ -387,6 +381,10 @@ export type UpdateDealSchema = {
|
|||||||
* Lexorank
|
* Lexorank
|
||||||
*/
|
*/
|
||||||
lexorank?: string | null;
|
lexorank?: string | null;
|
||||||
|
/**
|
||||||
|
* Boardid
|
||||||
|
*/
|
||||||
|
boardId?: number | null;
|
||||||
/**
|
/**
|
||||||
* Statusid
|
* Statusid
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -52,6 +52,15 @@ export const zCreateDealRequest = z.object({
|
|||||||
entity: zCreateDealSchema,
|
entity: zCreateDealSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StatusSchema
|
||||||
|
*/
|
||||||
|
export const zStatusSchema = z.object({
|
||||||
|
id: z.int(),
|
||||||
|
name: z.string(),
|
||||||
|
lexorank: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DealSchema
|
* DealSchema
|
||||||
*/
|
*/
|
||||||
@ -59,8 +68,8 @@ export const zDealSchema = z.object({
|
|||||||
id: z.int(),
|
id: z.int(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
lexorank: z.string(),
|
lexorank: z.string(),
|
||||||
statusId: z.int(),
|
status: zStatusSchema,
|
||||||
boardId: z.int(),
|
board: zBoardSchema,
|
||||||
createdAt: z.iso.datetime({
|
createdAt: z.iso.datetime({
|
||||||
offset: true,
|
offset: true,
|
||||||
}),
|
}),
|
||||||
@ -120,15 +129,6 @@ export const zCreateStatusRequest = z.object({
|
|||||||
entity: zCreateStatusSchema,
|
entity: zCreateStatusSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* StatusSchema
|
|
||||||
*/
|
|
||||||
export const zStatusSchema = z.object({
|
|
||||||
id: z.int(),
|
|
||||||
name: z.string(),
|
|
||||||
lexorank: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CreateStatusResponse
|
* CreateStatusResponse
|
||||||
*/
|
*/
|
||||||
@ -248,6 +248,7 @@ export const zUpdateBoardResponse = z.object({
|
|||||||
export const zUpdateDealSchema = z.object({
|
export const zUpdateDealSchema = z.object({
|
||||||
name: z.optional(z.union([z.string(), z.null()])),
|
name: z.optional(z.union([z.string(), z.null()])),
|
||||||
lexorank: z.optional(z.union([z.string(), z.null()])),
|
lexorank: z.optional(z.union([z.string(), z.null()])),
|
||||||
|
boardId: z.optional(z.union([z.int(), z.null()])),
|
||||||
statusId: z.optional(z.union([z.int(), z.null()])),
|
statusId: z.optional(z.union([z.int(), z.null()])),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user