feat: deals filters indicator and refactoring
This commit is contained in:
@ -6,7 +6,7 @@ import { useDealsContext } from "@/app/deals/contexts/DealsContext";
|
||||
import BaseTable from "@/components/ui/BaseTable/BaseTable";
|
||||
|
||||
const DealsTable: FC = () => {
|
||||
const { deals, paginationInfo, page, setPage, dealsFilters } =
|
||||
const { deals, paginationInfo, page, setPage, dealsFiltersForm } =
|
||||
useDealsContext();
|
||||
const columns = useDealsTableColumns();
|
||||
|
||||
@ -18,12 +18,18 @@ const DealsTable: FC = () => {
|
||||
records={[...deals]}
|
||||
columns={columns}
|
||||
sortStatus={{
|
||||
columnAccessor: dealsFilters.sortingField,
|
||||
direction: dealsFilters.sortingDirection,
|
||||
columnAccessor: dealsFiltersForm.values.sortingField ?? "",
|
||||
direction: dealsFiltersForm.values.sortingDirection,
|
||||
}}
|
||||
onSortStatusChange={sorting => {
|
||||
dealsFilters.setSortingField(sorting.columnAccessor);
|
||||
dealsFilters.setSortingDirection(sorting.direction);
|
||||
dealsFiltersForm.setFieldValue(
|
||||
"sortingField",
|
||||
sorting.columnAccessor
|
||||
);
|
||||
dealsFiltersForm.setFieldValue(
|
||||
"sortingDirection",
|
||||
sorting.direction
|
||||
);
|
||||
}}
|
||||
emptyState={
|
||||
<Group
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { IconEdit, IconFilter, IconPlus } from "@tabler/icons-react";
|
||||
import { Flex, Group } from "@mantine/core";
|
||||
import { Flex, Group, Indicator } from "@mantine/core";
|
||||
import { modals } from "@mantine/modals";
|
||||
import ToolPanelAction from "@/app/deals/components/desktop/ToolPanelAction/ToolPanelAction";
|
||||
import ViewSelector from "@/app/deals/components/desktop/ViewSelector/ViewSelector";
|
||||
@ -14,7 +14,7 @@ import { useDrawersContext } from "@/drawers/DrawersContext";
|
||||
import useIsMobile from "@/hooks/utils/useIsMobile";
|
||||
|
||||
const TopToolPanel = () => {
|
||||
const { dealsFilters } = useDealsContext();
|
||||
const { dealsFiltersForm, isChangedFilters } = useDealsContext();
|
||||
const { view } = useViewContext();
|
||||
const { projects, setSelectedProjectId, selectedProject, projectsCrud } =
|
||||
useProjectsContext();
|
||||
@ -52,11 +52,16 @@ const TopToolPanel = () => {
|
||||
gap={"sm"}>
|
||||
<DealsTableFiltersModal
|
||||
getOpener={onFiltersClick => (
|
||||
<ToolPanelAction onClick={onFiltersClick}>
|
||||
<IconFilter />
|
||||
</ToolPanelAction>
|
||||
<Indicator
|
||||
disabled={!isChangedFilters}
|
||||
offset={3}
|
||||
size={8}>
|
||||
<ToolPanelAction onClick={onFiltersClick}>
|
||||
<IconFilter />
|
||||
</ToolPanelAction>
|
||||
</Indicator>
|
||||
)}
|
||||
filters={dealsFilters}
|
||||
filtersForm={dealsFiltersForm}
|
||||
selectedProject={selectedProject}
|
||||
boardAndStatusEnabled={view === "table"}
|
||||
/>
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { UseFormReturnType } from "@mantine/form";
|
||||
import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
|
||||
import { DealsFilters } from "@/app/deals/hooks/useDealsFilters";
|
||||
import { DealsFiltersForm } from "@/app/deals/hooks/useDealsFilters";
|
||||
import { DealsCrud, useDealsCrud } from "@/hooks/cruds/useDealsCrud";
|
||||
import useDealsList from "@/hooks/lists/useDealsList";
|
||||
import { DealSchema, PaginationInfoSchema } from "@/lib/client";
|
||||
@ -16,7 +17,8 @@ type DealsContextState = {
|
||||
paginationInfo?: PaginationInfoSchema;
|
||||
page: number;
|
||||
setPage: React.Dispatch<React.SetStateAction<number>>;
|
||||
dealsFilters: DealsFilters;
|
||||
dealsFiltersForm: UseFormReturnType<DealsFiltersForm>;
|
||||
isChangedFilters: boolean;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
|
||||
@ -1,52 +1,48 @@
|
||||
import { Dispatch, SetStateAction, useState } from "react";
|
||||
import { isEqual } from "lodash";
|
||||
import { useForm, UseFormReturnType } from "@mantine/form";
|
||||
import { useDebouncedValue } from "@mantine/hooks";
|
||||
import { BoardSchema, SortDir, StatusSchema } from "@/lib/client";
|
||||
|
||||
export type DealsFilters = {
|
||||
export type DealsFiltersForm = {
|
||||
id?: number;
|
||||
debouncedId?: number;
|
||||
setId: Dispatch<SetStateAction<number | undefined>>;
|
||||
name?: string;
|
||||
debouncedName?: string;
|
||||
setName: Dispatch<SetStateAction<string | undefined>>;
|
||||
name: string;
|
||||
board: BoardSchema | null;
|
||||
setBoard: Dispatch<SetStateAction<BoardSchema | null>>;
|
||||
status: StatusSchema | null;
|
||||
setStatus: Dispatch<SetStateAction<StatusSchema | null>>;
|
||||
sortingField: string;
|
||||
setSortingField: Dispatch<SetStateAction<string>>;
|
||||
sortingField?: string;
|
||||
sortingDirection: SortDir;
|
||||
setSortingDirection: Dispatch<SetStateAction<SortDir>>;
|
||||
};
|
||||
|
||||
const useDealsFilters = (): DealsFilters => {
|
||||
const [id, setId] = useState<number>();
|
||||
const [debouncedId] = useDebouncedValue(id, 300);
|
||||
type ReturnType = {
|
||||
debouncedId: number | undefined;
|
||||
debouncedName: string;
|
||||
form: UseFormReturnType<DealsFiltersForm>;
|
||||
isChangedFilters: boolean;
|
||||
};
|
||||
|
||||
const [name, setName] = useState<string>();
|
||||
const [debouncedName] = useDebouncedValue(name, 300);
|
||||
const useDealsFilters = (): ReturnType => {
|
||||
const initialValues = {
|
||||
id: undefined,
|
||||
board: null,
|
||||
status: null,
|
||||
name: "",
|
||||
sortingField: "createdAt",
|
||||
sortingDirection: "asc" as SortDir,
|
||||
};
|
||||
|
||||
const [board, setBoard] = useState<BoardSchema | null>(null);
|
||||
const [status, setStatus] = useState<StatusSchema | null>(null);
|
||||
const form = useForm<DealsFiltersForm>({
|
||||
initialValues,
|
||||
});
|
||||
|
||||
const [sortingField, setSortingField] = useState("createdAt");
|
||||
const [sortingDirection, setSortingDirection] = useState<SortDir>("asc");
|
||||
const isChangedFilters = !isEqual(form.values, initialValues);
|
||||
|
||||
const [debouncedId] = useDebouncedValue(form.values.id, 300);
|
||||
const [debouncedName] = useDebouncedValue(form.values.name, 300);
|
||||
|
||||
return {
|
||||
id,
|
||||
setId,
|
||||
debouncedId,
|
||||
name,
|
||||
setName,
|
||||
debouncedName,
|
||||
board,
|
||||
setBoard,
|
||||
status,
|
||||
setStatus,
|
||||
sortingField,
|
||||
setSortingField,
|
||||
sortingDirection,
|
||||
setSortingDirection,
|
||||
form,
|
||||
isChangedFilters,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -2,21 +2,22 @@
|
||||
|
||||
import { ReactNode } from "react";
|
||||
import { Flex, Modal, NumberInput, rem, TextInput } from "@mantine/core";
|
||||
import { UseFormReturnType } from "@mantine/form";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { DealsFilters } from "@/app/deals/hooks/useDealsFilters";
|
||||
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 = {
|
||||
filters: DealsFilters;
|
||||
filtersForm: UseFormReturnType<DealsFiltersForm>;
|
||||
selectedProject: ProjectSchema | null;
|
||||
boardAndStatusEnabled: boolean;
|
||||
getOpener: (open: () => void) => ReactNode;
|
||||
};
|
||||
|
||||
const DealsTableFiltersModal = ({
|
||||
filters,
|
||||
filtersForm,
|
||||
selectedProject,
|
||||
boardAndStatusEnabled,
|
||||
getOpener,
|
||||
@ -36,34 +37,32 @@ const DealsTableFiltersModal = ({
|
||||
<NumberInput
|
||||
label={"ID"}
|
||||
placeholder={"Введите ID"}
|
||||
value={filters.id}
|
||||
{...filtersForm.getInputProps("id")}
|
||||
value={filtersForm.values.id}
|
||||
onChange={value =>
|
||||
typeof value === "number"
|
||||
? filters.setId(Number(value))
|
||||
: filters.setId(undefined)
|
||||
? filtersForm.setFieldValue("id", Number(value))
|
||||
: filtersForm.setFieldValue("id", undefined)
|
||||
}
|
||||
min={1}
|
||||
/>
|
||||
<TextInput
|
||||
label={"Название"}
|
||||
placeholder={"Введите название"}
|
||||
defaultValue={filters.name}
|
||||
onChange={event => filters.setName(event.target.value)}
|
||||
{...filtersForm.getInputProps("name")}
|
||||
/>
|
||||
{boardAndStatusEnabled && (
|
||||
<>
|
||||
<BoardSelect
|
||||
label={"Доска"}
|
||||
value={filters.board}
|
||||
onChange={filters.setBoard}
|
||||
{...filtersForm.getInputProps("board")}
|
||||
projectId={selectedProject?.id}
|
||||
clearable
|
||||
/>
|
||||
<StatusSelect
|
||||
label={"Статус"}
|
||||
value={filters.status}
|
||||
onChange={filters.setStatus}
|
||||
boardId={filters.board?.id}
|
||||
{...filtersForm.getInputProps("status")}
|
||||
boardId={filtersForm.values.board?.id}
|
||||
clearable
|
||||
/>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user