fix: scrolls and context for deal prefilling

This commit is contained in:
2024-10-18 12:28:22 +04:00
parent c1b9031672
commit aa6f0364b5
11 changed files with 207 additions and 161 deletions

View File

@@ -6,7 +6,7 @@ import CreateDealFrom from "../CreateDealForm/CreateDealFrom.tsx";
import { DealService } from "../../../client"; import { DealService } from "../../../client";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { dateWithoutTimezone } from "../../../shared/lib/date.ts"; import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx"; import { usePrefillDealContext } from "../../../pages/LeadsPage/contexts/PrefillDealContext.tsx";
type Props = { type Props = {
onClick: () => void; onClick: () => void;
@@ -15,7 +15,7 @@ const CreateDealButton: FC<Props> = () => {
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
const [isTransitionEnded, setIsTransitionEnded] = useState(true); const [isTransitionEnded, setIsTransitionEnded] = useState(true);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { prefillDeal, setPrefillDeal } = useDealPageContext(); const { prefillDeal, setPrefillDeal } = usePrefillDealContext();
return ( return (
<div <div
@@ -60,6 +60,7 @@ const CreateDealButton: FC<Props> = () => {
queryKey: ["getDealSummaries"], queryKey: ["getDealSummaries"],
}); });
setIsCreating(false); setIsCreating(false);
setPrefillDeal(undefined);
}); });
}} }}
/> />

View File

@@ -5,17 +5,18 @@ import { useForm } from "@mantine/form";
import styles from "./CreateDealForm.module.css"; import styles from "./CreateDealForm.module.css";
import ClientAutocomplete from "../../Selects/ClientAutocomplete/ClientAutocomplete.tsx"; import ClientAutocomplete from "../../Selects/ClientAutocomplete/ClientAutocomplete.tsx";
import { DateTimePicker } from "@mantine/dates"; import { DateTimePicker } from "@mantine/dates";
import ShippingWarehouseAutocomplete from "../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx"; import ShippingWarehouseAutocomplete
from "../../Selects/ShippingWarehouseAutocomplete/ShippingWarehouseAutocomplete.tsx";
import BaseMarketplaceSelect from "../../Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx"; import BaseMarketplaceSelect from "../../Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
import ServicePriceCategorySelect from "../../Selects/ServicePriceCategorySelect/ServicePriceCategorySelect.tsx"; import ServicePriceCategorySelect from "../../Selects/ServicePriceCategorySelect/ServicePriceCategorySelect.tsx";
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx"; import { usePrefillDealContext } from "../../../pages/LeadsPage/contexts/PrefillDealContext.tsx";
type Props = { type Props = {
onSubmit: (quickDeal: QuickDeal) => void; onSubmit: (quickDeal: QuickDeal) => void;
onCancel: () => void; onCancel: () => void;
}; };
const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => { const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => {
const { prefillOnOpen, prefillDeal } = useDealPageContext(); const { prefillOnOpen, prefillDeal } = usePrefillDealContext();
const form = useForm<QuickDeal>({ const form = useForm<QuickDeal>({
initialValues: { initialValues: {
name: "", name: "",

View File

@@ -1,19 +1,9 @@
import { createContext, Dispatch, FC, SetStateAction, useContext, useState } from "react"; import { createContext, FC, useContext, useState } from "react";
import { DealSchema, DealService } from "../../../client"; import { DealSchema } from "../../../client";
import { useDisclosure } from "@mantine/hooks";
type DealPageContextState = { type DealPageContextState = {
selectedDeal?: DealSchema; selectedDeal?: DealSchema;
setSelectedDeal: (deal: DealSchema | undefined) => void; setSelectedDeal: (deal: DealSchema | undefined) => void;
prefillOpened: boolean;
prefillOnClose: () => void;
prefillOnOpen: () => void;
selectedPrefillDeal?: DealSchema;
selectPrefillDeal: (dealId: number) => void;
prefillDeal?: DealSchema;
setPrefillDeal: Dispatch<SetStateAction<DealSchema | undefined>>;
}; };
const DealPageContext = createContext<DealPageContextState | undefined>( const DealPageContext = createContext<DealPageContextState | undefined>(
@@ -23,34 +13,10 @@ const useDealPageContextState = () => {
const [selectedDeal, setSelectedDeal] = useState<DealSchema | undefined>( const [selectedDeal, setSelectedDeal] = useState<DealSchema | undefined>(
undefined undefined
); );
const [selectedPrefillDeal, setSelectedPrefillDeal] = useState<DealSchema | undefined>(
undefined,
);
const [prefillDeal, setPrefillDeal] = useState<DealSchema | undefined>(
undefined,
);
const [prefillOpened, { open, close }] = useDisclosure(false);
const prefillOnClose = close;
const prefillOnOpen = open;
const selectPrefillDeal = (dealId: number) => {
DealService.getDealById({ dealId }).then(deal => {
setSelectedPrefillDeal(deal);
});
}
return { return {
selectedDeal, selectedDeal,
setSelectedDeal, setSelectedDeal,
prefillOpened,
prefillOnClose,
prefillOnOpen,
selectedPrefillDeal,
selectPrefillDeal,
prefillDeal,
setPrefillDeal,
}; };
}; };

View File

@@ -0,0 +1,71 @@
import { createContext, Dispatch, FC, SetStateAction, useContext, useState } from "react";
import { DealSchema, DealService } from "../../../client";
import { useDisclosure } from "@mantine/hooks";
type PrefillDealContextState = {
prefillOpened: boolean;
prefillOnClose: () => void;
prefillOnOpen: () => void;
selectedPrefillDeal?: DealSchema;
selectPrefillDeal: (dealId: number) => void;
prefillDeal?: DealSchema;
setPrefillDeal: Dispatch<SetStateAction<DealSchema | undefined>>;
};
const PrefillDealContext = createContext<PrefillDealContextState | undefined>(
undefined
);
const usePrefillDealContextState = () => {
const [selectedPrefillDeal, setSelectedPrefillDeal] = useState<DealSchema | undefined>(
undefined,
);
const [prefillDeal, setPrefillDeal] = useState<DealSchema | undefined>(
undefined,
);
const [prefillOpened, { open, close }] = useDisclosure(false);
const prefillOnClose = close;
const prefillOnOpen = open;
const selectPrefillDeal = (dealId: number) => {
DealService.getDealById({ dealId }).then(deal => {
setSelectedPrefillDeal(deal);
});
}
return {
prefillOpened,
prefillOnClose,
prefillOnOpen,
selectedPrefillDeal,
selectPrefillDeal,
prefillDeal,
setPrefillDeal,
};
};
type PrefillDealContextProviderProps = {
children: React.ReactNode;
};
export const PrefillDealContextProvider: FC<PrefillDealContextProviderProps> = ({
children,
}) => {
const state = usePrefillDealContextState();
return (
<PrefillDealContext.Provider value={state}>
{children}
</PrefillDealContext.Provider>
);
};
export const usePrefillDealContext = () => {
const context = useContext(PrefillDealContext);
if (!context) {
throw new Error(
"usePrefillDealContext must be used within a PrefillDealContextProvider"
);
}
return context;
};

View File

@@ -1,15 +1,15 @@
import { FC, useEffect } from "react"; import { FC, useEffect } from "react";
import { Button, Drawer, Flex, rem, TextInput } from "@mantine/core"; import { Button, Drawer, Flex, rem, TextInput } from "@mantine/core";
import { useDealPageContext } from "../../contexts/DealPageContext.tsx";
import DealsTable from "./components/tables/DealsTable/DealsTable.tsx"; import DealsTable from "./components/tables/DealsTable/DealsTable.tsx";
import Preview from "./components/Preview/Preview.tsx"; import Preview from "./components/Preview/Preview.tsx";
import styles from "./DealPrefillDrawer.module.css"; import styles from "./DealPrefillDrawer.module.css";
import BaseMarketplaceSelect from "../../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx"; import BaseMarketplaceSelect from "../../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
import usePrefillDeal from "./hooks/usePrefillDeal.tsx"; import usePrefillDeal from "./hooks/usePrefillDeal.tsx";
import { notifications } from "../../../../shared/lib/notifications.ts"; import { notifications } from "../../../../shared/lib/notifications.ts";
import { usePrefillDealContext } from "../../contexts/PrefillDealContext.tsx";
const DealPrefillDrawer: FC = () => { const DealPrefillDrawer: FC = () => {
const { prefillOpened, prefillOnClose, selectedPrefillDeal, setPrefillDeal, prefillDeal } = useDealPageContext(); const { prefillOpened, prefillOnClose, selectedPrefillDeal, setPrefillDeal, prefillDeal } = usePrefillDealContext();
const { data, form } = usePrefillDeal(); const { data, form } = usePrefillDeal();
useEffect(() => { useEffect(() => {

View File

@@ -1,7 +1,6 @@
.container { .container {
display: flex; display: flex;
gap: rem(10); gap: rem(10);
max-height: 95vh;
width: 50%; width: 50%;
} }
@@ -20,6 +19,7 @@
} }
.deal-container-wrapper { .deal-container-wrapper {
width: 100%;
border: dashed var(--item-border-size) var(--mantine-color-default-border); border: dashed var(--item-border-size) var(--mantine-color-default-border);
border-radius: var(--item-border-radius); border-radius: var(--item-border-radius);
padding: rem(10); padding: rem(10);

View File

@@ -1,12 +1,12 @@
import { FC } from "react"; import { FC } from "react";
import styles from "./Preview.module.css"; import styles from "./Preview.module.css";
import { ScrollArea, Skeleton, Title } from "@mantine/core"; import { ScrollArea, Skeleton, Title } from "@mantine/core";
import { useDealPageContext } from "../../../../contexts/DealPageContext.tsx";
import DealServicesTable from "../tables/DealServicesTable/DealServicesTable.tsx"; import DealServicesTable from "../tables/DealServicesTable/DealServicesTable.tsx";
import ProductPreview from "../ProductPreview/ProductPreview.tsx"; import ProductPreview from "../ProductPreview/ProductPreview.tsx";
import { usePrefillDealContext } from "../../../../contexts/PrefillDealContext.tsx";
const Preview: FC = () => { const Preview: FC = () => {
const { selectedPrefillDeal } = useDealPageContext(); const { selectedPrefillDeal } = usePrefillDealContext();
const getTotalPrice = () => { const getTotalPrice = () => {
if (!selectedPrefillDeal) return 0; if (!selectedPrefillDeal) return 0;
@@ -28,9 +28,10 @@ const Preview: FC = () => {
return ( return (
<div className={styles["container"]}> <div className={styles["container"]}>
<ScrollArea offsetScrollbars={"y"} w={"100%"}>
<Skeleton visible={!selectedPrefillDeal}>
<div className={styles["deal-container-wrapper"]}> <div className={styles["deal-container-wrapper"]}>
<ScrollArea offsetScrollbars={"y"} w={"100%"}>
<div style={{ height: "93vh" }}>
<Skeleton visible={!selectedPrefillDeal}>
<Title order={4} mb={18}> <Title order={4} mb={18}>
Общая стоимость всех услуг:{" "} Общая стоимость всех услуг:{" "}
{getTotalPrice().toLocaleString("ru")} {getTotalPrice().toLocaleString("ru")}
@@ -46,10 +47,11 @@ const Preview: FC = () => {
/> />
))} ))}
</div> </div>
</div>
</Skeleton> </Skeleton>
</div>
</ScrollArea> </ScrollArea>
</div> </div>
</div>
); );
}; };

View File

@@ -16,7 +16,6 @@ const DealServicesTable: FC<Props> = ({ items }) => {
<Flex <Flex
direction={"column"} direction={"column"}
gap={rem(10)} gap={rem(10)}
h={"100%"}
mb={10}> mb={10}>
<Flex <Flex
h={"100%"} h={"100%"}

View File

@@ -1,15 +1,15 @@
import { FC, useEffect } from "react"; import { FC, useEffect } from "react";
import useDealsTableColumns from "./columns.tsx"; import useDealsTableColumns from "./columns.tsx";
import { DealSummary } from "../../../../../../../client"; import { DealSummary } from "../../../../../../../client";
import { useDealPageContext } from "../../../../../contexts/DealPageContext.tsx";
import { BaseTable } from "../../../../../../../components/BaseTable/BaseTable.tsx"; import { BaseTable } from "../../../../../../../components/BaseTable/BaseTable.tsx";
import { usePrefillDealContext } from "../../../../../contexts/PrefillDealContext.tsx";
type Props = { type Props = {
items: DealSummary[]; items: DealSummary[];
}; };
const DealsTable: FC<Props> = ({ items }) => { const DealsTable: FC<Props> = ({ items }) => {
const { selectPrefillDeal } = useDealPageContext(); const { selectPrefillDeal } = usePrefillDealContext();
const columns = useDealsTableColumns(); const columns = useDealsTableColumns();
const defaultSorting = [{ id: "createdAt", desc: false }]; const defaultSorting = [{ id: "createdAt", desc: false }];
@@ -36,6 +36,9 @@ const DealsTable: FC<Props> = ({ items }) => {
mantinePaginationProps: { mantinePaginationProps: {
showRowsPerPage: false, showRowsPerPage: false,
}, },
enableStickyHeader: true,
enableStickyFooter: true,
mantineTableContainerProps: { style: { maxHeight: "81vh", height: "81vh" } },
} }
} }
/> />

View File

@@ -2,7 +2,7 @@ import { useMemo } from "react";
import { MRT_ColumnDef } from "mantine-react-table"; import { MRT_ColumnDef } from "mantine-react-table";
import { ActionIcon, Image, Radio } from "@mantine/core"; import { ActionIcon, Image, Radio } from "@mantine/core";
import { DealSummary } from "../../../../../../../client"; import { DealSummary } from "../../../../../../../client";
import { useDealPageContext } from "../../../../../contexts/DealPageContext.tsx"; import { usePrefillDealContext } from "../../../../../contexts/PrefillDealContext.tsx";
const useDealsTableColumns = () => { const useDealsTableColumns = () => {
return useMemo<MRT_ColumnDef<DealSummary>[]>( return useMemo<MRT_ColumnDef<DealSummary>[]>(
@@ -13,7 +13,7 @@ const useDealsTableColumns = () => {
size: 5, size: 5,
enableSorting: false, enableSorting: false,
Cell: ({ row }) => { Cell: ({ row }) => {
const { selectPrefillDeal, selectedPrefillDeal } = useDealPageContext(); const { selectPrefillDeal, selectedPrefillDeal } = usePrefillDealContext();
const checked = row.original.id === selectedPrefillDeal?.id; const checked = row.original.id === selectedPrefillDeal?.id;
return ( return (
<Radio <Radio

View File

@@ -21,6 +21,7 @@ import DealsTable from "../../DealsPage/components/DealsTable/DealsTable.tsx";
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { dateWithoutTimezone } from "../../../shared/lib/date.ts"; import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
import DealPrefillDrawer from "../drawers/DealPrefillDrawer/DealPrefillDrawer.tsx"; import DealPrefillDrawer from "../drawers/DealPrefillDrawer/DealPrefillDrawer.tsx";
import { PrefillDealContextProvider } from "../contexts/PrefillDealContext.tsx";
enum DisplayMode { enum DisplayMode {
BOARD, BOARD,
@@ -317,6 +318,7 @@ export const LeadsPage: FC = () => {
boxShadow: "none", boxShadow: "none",
}}> }}>
<DealPageContextProvider> <DealPageContextProvider>
<PrefillDealContextProvider>
<PageBlock style={{ flex: 0 }}> <PageBlock style={{ flex: 0 }}>
<Flex <Flex
align={"center"} align={"center"}
@@ -412,6 +414,7 @@ export const LeadsPage: FC = () => {
</PageBlock> </PageBlock>
<DealEditDrawer /> <DealEditDrawer />
<DealPrefillDrawer /> <DealPrefillDrawer />
</PrefillDealContextProvider>
</DealPageContextProvider> </DealPageContextProvider>
</PageBlock> </PageBlock>
); );