refactor: modals refactored
This commit is contained in:
@ -9,14 +9,8 @@ import { useDrawersContext } from "@/drawers/DrawersContext";
|
|||||||
import { DealSchema } from "@/lib/client";
|
import { DealSchema } from "@/lib/client";
|
||||||
|
|
||||||
const DealsTable: FC = () => {
|
const DealsTable: FC = () => {
|
||||||
const {
|
const { deals, paginationInfo, page, setPage, sortingForm, dealsCrud } =
|
||||||
deals,
|
useDealsContext();
|
||||||
paginationInfo,
|
|
||||||
page,
|
|
||||||
setPage,
|
|
||||||
dealsFiltersForm,
|
|
||||||
dealsCrud,
|
|
||||||
} = useDealsContext();
|
|
||||||
const { selectedProject } = useProjectsContext();
|
const { selectedProject } = useProjectsContext();
|
||||||
const { openDrawer } = useDrawersContext();
|
const { openDrawer } = useDrawersContext();
|
||||||
|
|
||||||
@ -40,20 +34,20 @@ const DealsTable: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
gap={"xs"}
|
gap={"xs"}
|
||||||
h={"calc(100vh - 125px)"}>
|
h={"calc(100vh - var(--mantine-spacing-xl) * 4)"}>
|
||||||
<BaseTable
|
<BaseTable
|
||||||
records={[...deals]}
|
records={[...deals]}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
sortStatus={{
|
sortStatus={{
|
||||||
columnAccessor: dealsFiltersForm.values.sortingField ?? "",
|
columnAccessor: sortingForm.values.sortingField ?? "",
|
||||||
direction: dealsFiltersForm.values.sortingDirection,
|
direction: sortingForm.values.sortingDirection,
|
||||||
}}
|
}}
|
||||||
onSortStatusChange={sorting => {
|
onSortStatusChange={sorting => {
|
||||||
dealsFiltersForm.setFieldValue(
|
sortingForm.setFieldValue(
|
||||||
"sortingField",
|
"sortingField",
|
||||||
sorting.columnAccessor
|
sorting.columnAccessor
|
||||||
);
|
);
|
||||||
dealsFiltersForm.setFieldValue(
|
sortingForm.setFieldValue(
|
||||||
"sortingDirection",
|
"sortingDirection",
|
||||||
sorting.direction
|
sorting.direction
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ const TopToolPanel: FC<Props> = ({ view, setView }) => {
|
|||||||
title: "Создание проекта",
|
title: "Создание проекта",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: projectsCrud.onCreate,
|
onChange: values => projectsCrud.onCreate(values.name),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -49,9 +49,15 @@ const TopToolPanel: FC<Props> = ({ view, setView }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const viewFiltersModalMap = {
|
||||||
|
table: "dealsTableFiltersModal",
|
||||||
|
board: "dealsBoardFiltersModal",
|
||||||
|
schedule: "dealsScheduleFiltersModal",
|
||||||
|
};
|
||||||
|
|
||||||
const onFiltersClick = () => {
|
const onFiltersClick = () => {
|
||||||
modals.openContextModal({
|
modals.openContextModal({
|
||||||
modal: "dealsFiltersModal",
|
modal: viewFiltersModalMap[view],
|
||||||
title: "Фильтры",
|
title: "Фильтры",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
|
|||||||
@ -29,8 +29,8 @@ const Board: FC<Props> = ({ board }) => {
|
|||||||
onMouseEnter={() => setIsHovered(true)}
|
onMouseEnter={() => setIsHovered(true)}
|
||||||
onMouseLeave={() => setIsHovered(false)}>
|
onMouseLeave={() => setIsHovered(false)}>
|
||||||
<InPlaceInput
|
<InPlaceInput
|
||||||
defaultValue={board.name}
|
value={board.name}
|
||||||
onComplete={value =>
|
onChange={value =>
|
||||||
boardsCrud.onUpdate(board.id, { name: value })
|
boardsCrud.onUpdate(board.id, { name: value })
|
||||||
}
|
}
|
||||||
inputStyles={{
|
inputStyles={{
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const CreateBoardButton = () => {
|
|||||||
<Flex style={{ borderBottom: "2px solid gray" }}>
|
<Flex style={{ borderBottom: "2px solid gray" }}>
|
||||||
<InPlaceInput
|
<InPlaceInput
|
||||||
placeholder={"Название доски"}
|
placeholder={"Название доски"}
|
||||||
onComplete={boardsCrud.onCreate}
|
onChange={boardsCrud.onCreate}
|
||||||
getChildren={startEditing => (
|
getChildren={startEditing => (
|
||||||
<Box
|
<Box
|
||||||
onClick={startEditing}
|
onClick={startEditing}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const CreateStatusButton = () => {
|
|||||||
className={styles["inner-container"]}>
|
className={styles["inner-container"]}>
|
||||||
<InPlaceInput
|
<InPlaceInput
|
||||||
placeholder={"Название колонки"}
|
placeholder={"Название колонки"}
|
||||||
onComplete={statusesCrud.onCreate}
|
onChange={statusesCrud.onCreate}
|
||||||
getChildren={startEditing => (
|
getChildren={startEditing => (
|
||||||
<Center
|
<Center
|
||||||
p={"sm"}
|
p={"sm"}
|
||||||
|
|||||||
@ -31,8 +31,8 @@ const StatusColumnHeader: FC<Props> = ({ status, isDragging }) => {
|
|||||||
mb={"xs"}
|
mb={"xs"}
|
||||||
className={styles.header}>
|
className={styles.header}>
|
||||||
<InPlaceInput
|
<InPlaceInput
|
||||||
defaultValue={status.name}
|
value={status.name}
|
||||||
onComplete={value => handleSave(value)}
|
onChange={value => handleSave(value)}
|
||||||
inputStyles={{
|
inputStyles={{
|
||||||
input: {
|
input: {
|
||||||
height: 25,
|
height: 25,
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
|
|||||||
import { DealsFiltersForm } from "@/app/deals/hooks/useDealsFilters";
|
import { DealsFiltersForm } from "@/app/deals/hooks/useDealsFilters";
|
||||||
import { DealsCrud, useDealsCrud } from "@/hooks/cruds/useDealsCrud";
|
import { DealsCrud, useDealsCrud } from "@/hooks/cruds/useDealsCrud";
|
||||||
import useDealsList from "@/hooks/lists/useDealsList";
|
import useDealsList from "@/hooks/lists/useDealsList";
|
||||||
|
import { SortingForm } from "@/hooks/utils/useSorting";
|
||||||
import { DealSchema, PaginationInfoSchema } from "@/lib/client";
|
import { DealSchema, PaginationInfoSchema } from "@/lib/client";
|
||||||
import makeContext from "@/lib/contextFactory/contextFactory";
|
import makeContext from "@/lib/contextFactory/contextFactory";
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ type DealsContextState = {
|
|||||||
setPage: React.Dispatch<React.SetStateAction<number>>;
|
setPage: React.Dispatch<React.SetStateAction<number>>;
|
||||||
dealsFiltersForm: UseFormReturnType<DealsFiltersForm>;
|
dealsFiltersForm: UseFormReturnType<DealsFiltersForm>;
|
||||||
isChangedFilters: boolean;
|
isChangedFilters: boolean;
|
||||||
|
sortingForm: UseFormReturnType<SortingForm>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const CreateStatusButton: FC = () => {
|
|||||||
title: "Создание колонки",
|
title: "Создание колонки",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: statusesCrud.onCreate,
|
onChange: values => statusesCrud.onCreate(values.name),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,8 +19,8 @@ const StatusMobile: FC<Props> = ({ status, board }) => {
|
|||||||
title: "Редактирование статуса",
|
title: "Редактирование статуса",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: name => statusesCrud.onUpdate(status.id, { name }),
|
onChange: values => statusesCrud.onUpdate(status.id, values),
|
||||||
defaultValue: status.name,
|
value: status,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,8 +18,8 @@ const BoardMobile: FC<Props> = ({ board }) => {
|
|||||||
title: "Редактирование доски",
|
title: "Редактирование доски",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: name => boardsCrud.onUpdate(board.id, { name }),
|
onChange: values => boardsCrud.onUpdate(board.id, values),
|
||||||
defaultValue: board.name,
|
value: board,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const CreateBoardButton: FC<Props> = ({ onCreateBoard }) => {
|
|||||||
title: "Создание доски",
|
title: "Создание доски",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: onCreateBoard,
|
onChange: values => onCreateBoard(values.name),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const CreateProjectButton: FC = () => {
|
|||||||
title: "Создание проекта",
|
title: "Создание проекта",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: projectsCrud.onCreate,
|
onChange: values => projectsCrud.onCreate(values.name),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,8 +25,8 @@ const ProjectMobile: FC<Props> = ({
|
|||||||
title: "Редактирование проекта",
|
title: "Редактирование проекта",
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete: name => projectsCrud.onUpdate(project.id, { name }),
|
onChange: values => projectsCrud.onUpdate(project.id, values),
|
||||||
defaultValue: project.name,
|
value: project,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
import { useForm, UseFormReturnType } from "@mantine/form";
|
import { useForm, UseFormReturnType } from "@mantine/form";
|
||||||
import { BoardSchema, SortDir, StatusSchema } from "@/lib/client";
|
import { BoardSchema, StatusSchema } from "@/lib/client";
|
||||||
|
|
||||||
export type DealsFiltersForm = {
|
export type DealsFiltersForm = {
|
||||||
id: number | null;
|
id: number | null;
|
||||||
name: string;
|
name: string;
|
||||||
board: BoardSchema | null;
|
board: BoardSchema | null;
|
||||||
status: StatusSchema | null;
|
status: StatusSchema | null;
|
||||||
sortingField?: string;
|
|
||||||
sortingDirection: SortDir;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type ReturnType = {
|
type ReturnType = {
|
||||||
@ -17,20 +15,18 @@ type ReturnType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const useDealsFilters = (): ReturnType => {
|
const useDealsFilters = (): ReturnType => {
|
||||||
const initialValues = {
|
const initialFilters = {
|
||||||
id: null,
|
id: null,
|
||||||
board: null,
|
board: null,
|
||||||
status: null,
|
status: null,
|
||||||
name: "",
|
name: "",
|
||||||
sortingField: "createdAt",
|
|
||||||
sortingDirection: "asc" as SortDir,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const form = useForm<DealsFiltersForm>({
|
const form = useForm<DealsFiltersForm>({
|
||||||
initialValues,
|
initialValues: initialFilters,
|
||||||
});
|
});
|
||||||
|
|
||||||
const isChangedFilters = !isEqual(form.values, initialValues);
|
const isChangedFilters = !isEqual(form.values, initialFilters);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
|
|||||||
@ -0,0 +1,71 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Flex,
|
||||||
|
NumberInput,
|
||||||
|
rem,
|
||||||
|
Space,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useForm } from "@mantine/form";
|
||||||
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
|
import { DealsFiltersForm } from "@/app/deals/hooks/useDealsFilters";
|
||||||
|
import { ProjectSchema } from "@/lib/client";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: DealsFiltersForm;
|
||||||
|
onChange: (values: DealsFiltersForm) => void;
|
||||||
|
project: ProjectSchema | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DealsBoardFiltersModal = ({
|
||||||
|
id,
|
||||||
|
context,
|
||||||
|
innerProps,
|
||||||
|
}: ContextModalProps<Props>) => {
|
||||||
|
const filtersForm = useForm({
|
||||||
|
initialValues: innerProps.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: DealsFiltersForm) => {
|
||||||
|
innerProps.onChange(values);
|
||||||
|
context.closeModal(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={filtersForm.onSubmit(onSubmit)}>
|
||||||
|
<Flex
|
||||||
|
gap={rem(10)}
|
||||||
|
direction={"column"}>
|
||||||
|
<NumberInput
|
||||||
|
label={"ID"}
|
||||||
|
placeholder={"Введите ID"}
|
||||||
|
{...filtersForm.getInputProps("id")}
|
||||||
|
value={filtersForm.values.id ?? ""}
|
||||||
|
onChange={value =>
|
||||||
|
typeof value === "number"
|
||||||
|
? filtersForm.setFieldValue("id", Number(value))
|
||||||
|
: filtersForm.setFieldValue("id", null)
|
||||||
|
}
|
||||||
|
hideControls
|
||||||
|
min={1}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label={"Название"}
|
||||||
|
placeholder={"Введите название"}
|
||||||
|
{...filtersForm.getInputProps("name")}
|
||||||
|
/>
|
||||||
|
<Space />
|
||||||
|
<Button
|
||||||
|
variant={"default"}
|
||||||
|
type={"submit"}>
|
||||||
|
<Text>Сохранить</Text>
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DealsBoardFiltersModal;
|
||||||
@ -20,10 +20,9 @@ type Props = {
|
|||||||
value: DealsFiltersForm;
|
value: DealsFiltersForm;
|
||||||
onChange: (values: DealsFiltersForm) => void;
|
onChange: (values: DealsFiltersForm) => void;
|
||||||
project: ProjectSchema | null;
|
project: ProjectSchema | null;
|
||||||
boardAndStatusEnabled: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const DealsFiltersModal = ({
|
const DealsScheduleFiltersModal = ({
|
||||||
id,
|
id,
|
||||||
context,
|
context,
|
||||||
innerProps,
|
innerProps,
|
||||||
@ -60,23 +59,19 @@ const DealsFiltersModal = ({
|
|||||||
placeholder={"Введите название"}
|
placeholder={"Введите название"}
|
||||||
{...filtersForm.getInputProps("name")}
|
{...filtersForm.getInputProps("name")}
|
||||||
/>
|
/>
|
||||||
{innerProps.boardAndStatusEnabled && (
|
<BoardSelect
|
||||||
<>
|
label={"Доска"}
|
||||||
<BoardSelect
|
{...filtersForm.getInputProps("board")}
|
||||||
label={"Доска"}
|
projectId={innerProps.project?.id}
|
||||||
{...filtersForm.getInputProps("board")}
|
clearable
|
||||||
projectId={innerProps.project?.id}
|
/>
|
||||||
clearable
|
<StatusSelect
|
||||||
/>
|
label={"Статус"}
|
||||||
<StatusSelect
|
{...filtersForm.getInputProps("status")}
|
||||||
label={"Статус"}
|
boardId={filtersForm.values.board?.id}
|
||||||
{...filtersForm.getInputProps("status")}
|
clearable
|
||||||
boardId={filtersForm.values.board?.id}
|
clearOnBoardChange
|
||||||
clearable
|
/>
|
||||||
clearOnBoardChange
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Space />
|
<Space />
|
||||||
<Button
|
<Button
|
||||||
variant={"default"}
|
variant={"default"}
|
||||||
@ -88,4 +83,4 @@ const DealsFiltersModal = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DealsFiltersModal;
|
export default DealsScheduleFiltersModal;
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Flex,
|
||||||
|
NumberInput,
|
||||||
|
rem,
|
||||||
|
Space,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
} from "@mantine/core";
|
||||||
|
import { useForm } from "@mantine/form";
|
||||||
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
|
import { DealsFiltersForm } from "@/app/deals/hooks/useDealsFilters";
|
||||||
|
import BoardSelect from "@/components/selects/BoardSelect/BoardSelect";
|
||||||
|
import StatusSelect from "@/components/selects/StatusSelect/StatusSelect";
|
||||||
|
import { ProjectSchema } from "@/lib/client";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: DealsFiltersForm;
|
||||||
|
onChange: (values: DealsFiltersForm) => void;
|
||||||
|
project: ProjectSchema | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DealsTableFiltersModal = ({
|
||||||
|
id,
|
||||||
|
context,
|
||||||
|
innerProps,
|
||||||
|
}: ContextModalProps<Props>) => {
|
||||||
|
const filtersForm = useForm({
|
||||||
|
initialValues: innerProps.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: DealsFiltersForm) => {
|
||||||
|
innerProps.onChange(values);
|
||||||
|
context.closeModal(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={filtersForm.onSubmit(onSubmit)}>
|
||||||
|
<Flex
|
||||||
|
gap={rem(10)}
|
||||||
|
direction={"column"}>
|
||||||
|
<NumberInput
|
||||||
|
label={"ID"}
|
||||||
|
placeholder={"Введите ID"}
|
||||||
|
{...filtersForm.getInputProps("id")}
|
||||||
|
value={filtersForm.values.id ?? ""}
|
||||||
|
onChange={value =>
|
||||||
|
typeof value === "number"
|
||||||
|
? filtersForm.setFieldValue("id", Number(value))
|
||||||
|
: filtersForm.setFieldValue("id", null)
|
||||||
|
}
|
||||||
|
hideControls
|
||||||
|
min={1}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label={"Название"}
|
||||||
|
placeholder={"Введите название"}
|
||||||
|
{...filtersForm.getInputProps("name")}
|
||||||
|
/>
|
||||||
|
<BoardSelect
|
||||||
|
label={"Доска"}
|
||||||
|
{...filtersForm.getInputProps("board")}
|
||||||
|
projectId={innerProps.project?.id}
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
<StatusSelect
|
||||||
|
label={"Статус"}
|
||||||
|
{...filtersForm.getInputProps("status")}
|
||||||
|
boardId={filtersForm.values.board?.id}
|
||||||
|
clearable
|
||||||
|
clearOnBoardChange
|
||||||
|
/>
|
||||||
|
<Space />
|
||||||
|
<Button
|
||||||
|
variant={"default"}
|
||||||
|
type={"submit"}>
|
||||||
|
<Text>Сохранить</Text>
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DealsTableFiltersModal;
|
||||||
@ -5,8 +5,8 @@ import InPlaceInputDesktop from "./InPlaceInputDesktop";
|
|||||||
import InPlaceInputMobile from "./InPlaceInputMobile";
|
import InPlaceInputMobile from "./InPlaceInputMobile";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
defaultValue?: string;
|
value?: string;
|
||||||
onComplete: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
getChildren: (startEditing: () => void) => ReactNode;
|
getChildren: (startEditing: () => void) => ReactNode;
|
||||||
inputStyles?: Styles<any>;
|
inputStyles?: Styles<any>;
|
||||||
|
|||||||
@ -3,22 +3,22 @@ import { TextInput } from "@mantine/core";
|
|||||||
import { Styles } from "@mantine/core/lib/core/styles-api/styles-api.types";
|
import { Styles } from "@mantine/core/lib/core/styles-api/styles-api.types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
defaultValue?: string;
|
value?: string;
|
||||||
onComplete: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
getChildren: (startEditing: () => void) => ReactNode;
|
getChildren: (startEditing: () => void) => ReactNode;
|
||||||
inputStyles?: Styles<any>;
|
inputStyles?: Styles<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const InPlaceInputDesktop: FC<Props> = ({
|
const InPlaceInputDesktop: FC<Props> = ({
|
||||||
onComplete,
|
onChange,
|
||||||
placeholder,
|
placeholder,
|
||||||
inputStyles,
|
inputStyles,
|
||||||
getChildren,
|
getChildren,
|
||||||
defaultValue = "",
|
value = "",
|
||||||
}) => {
|
}) => {
|
||||||
const [isWriting, setIsWriting] = useState<boolean>(false);
|
const [isWriting, setIsWriting] = useState<boolean>(false);
|
||||||
const [value, setValue] = useState<string>(defaultValue);
|
const [localValue, setLocalValue] = useState<string>(value);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -41,22 +41,22 @@ const InPlaceInputDesktop: FC<Props> = ({
|
|||||||
document.addEventListener("mousedown", handleClickOutside);
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
return () =>
|
return () =>
|
||||||
document.removeEventListener("mousedown", handleClickOutside);
|
document.removeEventListener("mousedown", handleClickOutside);
|
||||||
}, [isWriting, value]);
|
}, [isWriting, localValue]);
|
||||||
|
|
||||||
const onStartCreating = () => {
|
const onStartCreating = () => {
|
||||||
setValue(defaultValue);
|
setLocalValue(localValue);
|
||||||
setIsWriting(true);
|
setIsWriting(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCancelCreating = () => {
|
const onCancelCreating = () => {
|
||||||
setValue(defaultValue);
|
setLocalValue(localValue);
|
||||||
setIsWriting(false);
|
setIsWriting(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCompleteCreating = () => {
|
const onCompleteCreating = () => {
|
||||||
const localValue = value.trim();
|
const val = localValue.trim();
|
||||||
if (localValue) {
|
if (val) {
|
||||||
onComplete(localValue);
|
onChange(val);
|
||||||
}
|
}
|
||||||
setIsWriting(false);
|
setIsWriting(false);
|
||||||
};
|
};
|
||||||
@ -67,8 +67,8 @@ const InPlaceInputDesktop: FC<Props> = ({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
variant={"unstyled"}
|
variant={"unstyled"}
|
||||||
value={value}
|
value={localValue}
|
||||||
onChange={e => setValue(e.target.value)}
|
onChange={e => setLocalValue(e.target.value)}
|
||||||
onKeyDown={e => {
|
onKeyDown={e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.key === "Enter") onCompleteCreating();
|
if (e.key === "Enter") onCompleteCreating();
|
||||||
|
|||||||
@ -2,17 +2,17 @@ import { FC, ReactNode } from "react";
|
|||||||
import { modals } from "@mantine/modals";
|
import { modals } from "@mantine/modals";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
defaultValue?: string;
|
value?: string;
|
||||||
onComplete: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
getChildren: (startEditing: () => void) => ReactNode;
|
getChildren: (startEditing: () => void) => ReactNode;
|
||||||
modalTitle?: string;
|
modalTitle?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const InPlaceInputMobile: FC<Props> = ({
|
const InPlaceInputMobile: FC<Props> = ({
|
||||||
onComplete,
|
onChange,
|
||||||
getChildren,
|
getChildren,
|
||||||
modalTitle = "",
|
modalTitle = "",
|
||||||
defaultValue = "",
|
value = "",
|
||||||
}) => {
|
}) => {
|
||||||
const onStartCreating = () => {
|
const onStartCreating = () => {
|
||||||
modals.openContextModal({
|
modals.openContextModal({
|
||||||
@ -20,8 +20,8 @@ const InPlaceInputMobile: FC<Props> = ({
|
|||||||
title: modalTitle,
|
title: modalTitle,
|
||||||
withCloseButton: true,
|
withCloseButton: true,
|
||||||
innerProps: {
|
innerProps: {
|
||||||
onComplete,
|
onChange: values => onChange(values.name),
|
||||||
defaultValue,
|
value: { name: value },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { useDebouncedValue } from "@mantine/hooks";
|
|||||||
import useDealsFilters, {
|
import useDealsFilters, {
|
||||||
DealsFiltersForm,
|
DealsFiltersForm,
|
||||||
} from "@/app/deals/hooks/useDealsFilters";
|
} from "@/app/deals/hooks/useDealsFilters";
|
||||||
|
import useSorting, { SortingForm } from "@/hooks/utils/useSorting";
|
||||||
import { DealSchema, GetDealsData, PaginationInfoSchema } from "@/lib/client";
|
import { DealSchema, GetDealsData, PaginationInfoSchema } from "@/lib/client";
|
||||||
import {
|
import {
|
||||||
getDealsOptions,
|
getDealsOptions,
|
||||||
@ -22,6 +23,7 @@ type ReturnType = {
|
|||||||
setDeals: (deals: DealSchema[]) => void;
|
setDeals: (deals: DealSchema[]) => void;
|
||||||
dealsFiltersForm: UseFormReturnType<DealsFiltersForm>;
|
dealsFiltersForm: UseFormReturnType<DealsFiltersForm>;
|
||||||
isChangedFilters: boolean;
|
isChangedFilters: boolean;
|
||||||
|
sortingForm: UseFormReturnType<SortingForm>;
|
||||||
refetchDeals: () => void;
|
refetchDeals: () => void;
|
||||||
page: number;
|
page: number;
|
||||||
setPage: Dispatch<SetStateAction<number>>;
|
setPage: Dispatch<SetStateAction<number>>;
|
||||||
@ -37,22 +39,32 @@ const useDealsList = ({
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const itemsPerPage = 10;
|
const itemsPerPage = 10;
|
||||||
const { form, isChangedFilters } = useDealsFilters();
|
const { form: dealsFiltersForm, isChangedFilters } = useDealsFilters();
|
||||||
|
const { form: sortingForm } = useSorting();
|
||||||
|
|
||||||
const [debouncedId] = useDebouncedValue(form.values.id, 300);
|
const [debouncedId] = useDebouncedValue(dealsFiltersForm.values.id, 300);
|
||||||
const [debouncedName] = useDebouncedValue(form.values.name, 300);
|
const [debouncedName] = useDebouncedValue(
|
||||||
|
dealsFiltersForm.values.name,
|
||||||
|
300
|
||||||
|
);
|
||||||
|
|
||||||
const options: Omit<GetDealsData, "url"> = {
|
const options: Omit<GetDealsData, "url"> = {
|
||||||
query: {
|
query: {
|
||||||
page: withPagination ? page : null,
|
page: withPagination ? page : null,
|
||||||
itemsPerPage: withPagination ? itemsPerPage : null,
|
itemsPerPage: withPagination ? itemsPerPage : null,
|
||||||
sortingField: withPagination ? form.values.sortingField : null,
|
sortingField: withPagination
|
||||||
|
? sortingForm.values.sortingField
|
||||||
|
: null,
|
||||||
sortingDirection: withPagination
|
sortingDirection: withPagination
|
||||||
? form.values.sortingDirection
|
? sortingForm.values.sortingDirection
|
||||||
: null,
|
: null,
|
||||||
projectId: withPagination ? projectId : null,
|
projectId: withPagination ? projectId : null,
|
||||||
boardId: withPagination ? form.values.board?.id : boardId,
|
boardId: withPagination
|
||||||
statusId: withPagination ? form.values.status?.id : null,
|
? dealsFiltersForm.values.board?.id
|
||||||
|
: boardId,
|
||||||
|
statusId: withPagination
|
||||||
|
? dealsFiltersForm.values.status?.id
|
||||||
|
: null,
|
||||||
name: debouncedName,
|
name: debouncedName,
|
||||||
id: debouncedId,
|
id: debouncedId,
|
||||||
},
|
},
|
||||||
@ -72,7 +84,8 @@ const useDealsList = ({
|
|||||||
return {
|
return {
|
||||||
deals: data?.items ?? [],
|
deals: data?.items ?? [],
|
||||||
setDeals,
|
setDeals,
|
||||||
dealsFiltersForm: form,
|
dealsFiltersForm,
|
||||||
|
sortingForm,
|
||||||
isChangedFilters,
|
isChangedFilters,
|
||||||
refetchDeals: refetch,
|
refetchDeals: refetch,
|
||||||
page,
|
page,
|
||||||
|
|||||||
28
src/hooks/utils/useSorting.ts
Normal file
28
src/hooks/utils/useSorting.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { useForm, UseFormReturnType } from "@mantine/form";
|
||||||
|
import { SortDir } from "@/lib/client";
|
||||||
|
|
||||||
|
export type SortingForm = {
|
||||||
|
sortingField?: string;
|
||||||
|
sortingDirection: SortDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ReturnType = {
|
||||||
|
form: UseFormReturnType<SortingForm>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useSorting = (): ReturnType => {
|
||||||
|
const initialFilters = {
|
||||||
|
sortingField: "createdAt",
|
||||||
|
sortingDirection: "asc" as SortDir,
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = useForm<SortingForm>({
|
||||||
|
initialValues: initialFilters,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
form,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useSorting;
|
||||||
@ -4,23 +4,23 @@ import { Button, Flex, rem, TextInput } from "@mantine/core";
|
|||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
import { ContextModalProps } from "@mantine/modals";
|
import { ContextModalProps } from "@mantine/modals";
|
||||||
|
|
||||||
type Props = {
|
|
||||||
onComplete: (value: string) => void;
|
|
||||||
defaultValue?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type FormType = {
|
type FormType = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onChange: (value: FormType) => void;
|
||||||
|
value?: FormType;
|
||||||
|
};
|
||||||
|
|
||||||
const EnterNameModal = ({
|
const EnterNameModal = ({
|
||||||
id,
|
id,
|
||||||
context,
|
context,
|
||||||
innerProps,
|
innerProps,
|
||||||
}: ContextModalProps<Props>) => {
|
}: ContextModalProps<Props>) => {
|
||||||
const form = useForm<FormType>({
|
const form = useForm<FormType>({
|
||||||
initialValues: {
|
initialValues: innerProps.value || {
|
||||||
name: innerProps.defaultValue ?? "",
|
name: "",
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
name: name => !name && "Введите название",
|
name: name => !name && "Введите название",
|
||||||
@ -28,7 +28,7 @@ const EnterNameModal = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = (values: FormType) => {
|
const onSubmit = (values: FormType) => {
|
||||||
innerProps.onComplete(values.name);
|
innerProps.onChange(values);
|
||||||
context.closeModal(id);
|
context.closeModal(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
import DealsFiltersModal from "@/app/deals/modals/DealsFiltersModal/DealsFiltersModal";
|
import DealsBoardFiltersModal from "@/app/deals/modals/DealsBoardFiltersModal/DealsBoardFiltersModal";
|
||||||
|
import DealsScheduleFiltersModal from "@/app/deals/modals/DealsScheduleFiltersModal/DealsScheduleFiltersModal";
|
||||||
|
import DealsTableFiltersModal from "@/app/deals/modals/DealsTableFiltersModal/DealsTableFiltersModal";
|
||||||
import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal";
|
import EnterNameModal from "@/modals/EnterNameModal/EnterNameModal";
|
||||||
|
|
||||||
export const modals = {
|
export const modals = {
|
||||||
enterNameModal: EnterNameModal,
|
enterNameModal: EnterNameModal,
|
||||||
dealsFiltersModal: DealsFiltersModal,
|
dealsTableFiltersModal: DealsTableFiltersModal,
|
||||||
|
dealsBoardFiltersModal: DealsBoardFiltersModal,
|
||||||
|
dealsScheduleFiltersModal: DealsScheduleFiltersModal,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user