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

@@ -1,19 +1,9 @@
import { createContext, Dispatch, FC, SetStateAction, useContext, useState } from "react";
import { DealSchema, DealService } from "../../../client";
import { useDisclosure } from "@mantine/hooks";
import { createContext, FC, useContext, useState } from "react";
import { DealSchema } from "../../../client";
type DealPageContextState = {
selectedDeal?: DealSchema;
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>(
@@ -23,34 +13,10 @@ const useDealPageContextState = () => {
const [selectedDeal, setSelectedDeal] = useState<DealSchema | 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 {
selectedDeal,
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 { Button, Drawer, Flex, rem, TextInput } from "@mantine/core";
import { useDealPageContext } from "../../contexts/DealPageContext.tsx";
import DealsTable from "./components/tables/DealsTable/DealsTable.tsx";
import Preview from "./components/Preview/Preview.tsx";
import styles from "./DealPrefillDrawer.module.css";
import BaseMarketplaceSelect from "../../../../components/Selects/BaseMarketplaceSelect/BaseMarketplaceSelect.tsx";
import usePrefillDeal from "./hooks/usePrefillDeal.tsx";
import { notifications } from "../../../../shared/lib/notifications.ts";
import { usePrefillDealContext } from "../../contexts/PrefillDealContext.tsx";
const DealPrefillDrawer: FC = () => {
const { prefillOpened, prefillOnClose, selectedPrefillDeal, setPrefillDeal, prefillDeal } = useDealPageContext();
const { prefillOpened, prefillOnClose, selectedPrefillDeal, setPrefillDeal, prefillDeal } = usePrefillDealContext();
const { data, form } = usePrefillDeal();
useEffect(() => {

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,15 @@
import { FC, useEffect } from "react";
import useDealsTableColumns from "./columns.tsx";
import { DealSummary } from "../../../../../../../client";
import { useDealPageContext } from "../../../../../contexts/DealPageContext.tsx";
import { BaseTable } from "../../../../../../../components/BaseTable/BaseTable.tsx";
import { usePrefillDealContext } from "../../../../../contexts/PrefillDealContext.tsx";
type Props = {
items: DealSummary[];
};
const DealsTable: FC<Props> = ({ items }) => {
const { selectPrefillDeal } = useDealPageContext();
const { selectPrefillDeal } = usePrefillDealContext();
const columns = useDealsTableColumns();
const defaultSorting = [{ id: "createdAt", desc: false }];
@@ -36,6 +36,9 @@ const DealsTable: FC<Props> = ({ items }) => {
mantinePaginationProps: {
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 { ActionIcon, Image, Radio } from "@mantine/core";
import { DealSummary } from "../../../../../../../client";
import { useDealPageContext } from "../../../../../contexts/DealPageContext.tsx";
import { usePrefillDealContext } from "../../../../../contexts/PrefillDealContext.tsx";
const useDealsTableColumns = () => {
return useMemo<MRT_ColumnDef<DealSummary>[]>(
@@ -13,7 +13,7 @@ const useDealsTableColumns = () => {
size: 5,
enableSorting: false,
Cell: ({ row }) => {
const { selectPrefillDeal, selectedPrefillDeal } = useDealPageContext();
const { selectPrefillDeal, selectedPrefillDeal } = usePrefillDealContext();
const checked = row.original.id === selectedPrefillDeal?.id;
return (
<Radio

View File

@@ -21,6 +21,7 @@ import DealsTable from "../../DealsPage/components/DealsTable/DealsTable.tsx";
import { motion } from "framer-motion";
import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
import DealPrefillDrawer from "../drawers/DealPrefillDrawer/DealPrefillDrawer.tsx";
import { PrefillDealContextProvider } from "../contexts/PrefillDealContext.tsx";
enum DisplayMode {
BOARD,
@@ -317,101 +318,103 @@ export const LeadsPage: FC = () => {
boxShadow: "none",
}}>
<DealPageContextProvider>
<PageBlock style={{ flex: 0 }}>
<Flex
align={"center"}
justify={"space-between"}>
<PrefillDealContextProvider>
<PageBlock style={{ flex: 0 }}>
<Flex
gap={rem(10)}
direction={"column"}
align={"center"}>
<Text size={"xs"}>Вид</Text>
<Flex gap={rem(10)}>
<ActionIcon
onClick={() =>
setDisplayMode(DisplayMode.BOARD)
}
variant={
displayMode === DisplayMode.BOARD
? "filled"
: "default"
}>
<IconMenuDeep
style={{ rotate: "-90deg" }}
/>
</ActionIcon>
<ActionIcon
onClick={() =>
setDisplayMode(DisplayMode.TABLE)
}
variant={
displayMode === DisplayMode.TABLE
? "filled"
: "default"
}>
<IconMenu2 />
</ActionIcon>
align={"center"}
justify={"space-between"}>
<Flex
gap={rem(10)}
direction={"column"}
align={"center"}>
<Text size={"xs"}>Вид</Text>
<Flex gap={rem(10)}>
<ActionIcon
onClick={() =>
setDisplayMode(DisplayMode.BOARD)
}
variant={
displayMode === DisplayMode.BOARD
? "filled"
: "default"
}>
<IconMenuDeep
style={{ rotate: "-90deg" }}
/>
</ActionIcon>
<ActionIcon
onClick={() =>
setDisplayMode(DisplayMode.TABLE)
}
variant={
displayMode === DisplayMode.TABLE
? "filled"
: "default"
}>
<IconMenu2 />
</ActionIcon>
</Flex>
</Flex>
<motion.div
key={displayMode}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.2 }}>
<div
className={styles["top-panel"]}
style={{
display:
displayMode === DisplayMode.TABLE
? "flex"
: "none",
}}>
<NumberInput
min={1}
placeholder={"Введите номер"}
{...form.getInputProps("id")}
hideControls
/>
<DealStatusSelect
onClear={() =>
form.setFieldValue("dealStatus", null)
}
clearable
placeholder={"Выберите статус "}
{...form.getInputProps("dealStatus")}
/>
<BaseMarketplaceSelect
onClear={() =>
form.setFieldValue("marketplace", null)
}
clearable
placeholder={"Выберите маркетплейс"}
{...form.getInputProps("marketplace")}
/>
<ClientSelectNew
onClear={() =>
form.setFieldValue("client", null)
}
clearable
searchable
placeholder={"Выберите клиента"}
{...form.getInputProps("client")}
/>
</div>
</motion.div>
</Flex>
<motion.div
key={displayMode}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.2 }}>
<div
className={styles["top-panel"]}
style={{
display:
displayMode === DisplayMode.TABLE
? "flex"
: "none",
}}>
<NumberInput
min={1}
placeholder={"Введите номер"}
{...form.getInputProps("id")}
hideControls
/>
<DealStatusSelect
onClear={() =>
form.setFieldValue("dealStatus", null)
}
clearable
placeholder={"Выберите статус "}
{...form.getInputProps("dealStatus")}
/>
<BaseMarketplaceSelect
onClear={() =>
form.setFieldValue("marketplace", null)
}
clearable
placeholder={"Выберите маркетплейс"}
{...form.getInputProps("marketplace")}
/>
<ClientSelectNew
onClear={() =>
form.setFieldValue("client", null)
}
clearable
searchable
placeholder={"Выберите клиента"}
{...form.getInputProps("client")}
/>
</div>
</motion.div>
</Flex>
</PageBlock>
<PageBlock
style={{
display: "flex",
flexDirection: "column",
flex: 1,
height: "100%",
}}>
{getBody()}
</PageBlock>
<DealEditDrawer />
<DealPrefillDrawer />
</PageBlock>
<PageBlock
style={{
display: "flex",
flexDirection: "column",
flex: 1,
height: "100%",
}}>
{getBody()}
</PageBlock>
<DealEditDrawer />
<DealPrefillDrawer />
</PrefillDealContextProvider>
</DealPageContextProvider>
</PageBlock>
);