This commit is contained in:
aleksandr-raw 2024-04-16 14:57:38 +04:00
parent f7bca1ae82
commit 28cd507004
10 changed files with 333 additions and 64 deletions

@ -1,4 +1,4 @@
import { useMediaQuery, useTheme } from "@mui/material";
import { useTheme } from "@mui/material";
import {
Dispatch,
FC,
@ -9,7 +9,8 @@ import {
} from "react";
import { ItemsSelectionView } from "./ItemsSelectionView/ItemsSelectionView";
import { ItemDetailsView } from "./ItemDetailsView/ItemDetailsView";
import { TQuestionEntity } from "../IntegrationsModal";
import { TitleKeys, TQuestionEntity } from "../IntegrationsModal";
import Box from "@mui/material/Box";
type IntegrationStep6Props = {
handlePrevStep: () => void;
@ -25,7 +26,6 @@ export const IntegrationStep6: FC<IntegrationStep6Props> = ({
setQuestionEntity,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const [isSelection, setIsSelection] = useState<boolean>(false);
const [activeItem, setActiveItem] = useState<string | null>(null);
const [selectedValue, setSelectedValue] = useState<string | null>(null);
@ -35,7 +35,7 @@ export const IntegrationStep6: FC<IntegrationStep6Props> = ({
setQuestionEntity((prevState) => ({
...prevState,
[activeItem]: [selectedValue],
[activeItem]: [...prevState[activeItem as TitleKeys], selectedValue],
}));
}, [activeItem, setQuestionEntity, selectedValue]);
@ -45,7 +45,14 @@ export const IntegrationStep6: FC<IntegrationStep6Props> = ({
);
return (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
height: "100%",
flexGrow: 1,
}}
>
{isSelection ? (
<ItemsSelectionView
items={items}
@ -70,6 +77,6 @@ export const IntegrationStep6: FC<IntegrationStep6Props> = ({
setActiveItem={setActiveItem}
/>
)}
</>
</Box>
);
};

@ -2,16 +2,17 @@ import { Box, Typography, useTheme } from "@mui/material";
import { FC } from "react";
type AnswerItemProps = {
text: string;
fieldName: string;
fieldValue: string;
};
export const AnswerItem: FC<AnswerItemProps> = ({ text }) => {
export const AnswerItem: FC<AnswerItemProps> = ({ fieldName, fieldValue }) => {
const theme = useTheme();
return (
<Box
sx={{
padding: "10px 20px",
height: "130px",
height: "140px",
borderBottom: `1px solid ${theme.palette.background.default}`,
}}
>
@ -22,7 +23,16 @@ export const AnswerItem: FC<AnswerItemProps> = ({ text }) => {
color: theme.palette.grey3.main,
}}
>
{text}
{fieldName}
</Typography>
<Typography
sx={{
fontSize: "14px",
fontWeight: 400,
color: theme.palette.grey3.main,
}}
>
{fieldValue}
</Typography>
</Box>
);

@ -2,29 +2,33 @@ import { Box, Typography, useTheme } from "@mui/material";
import { FC } from "react";
import { IconBtnAdd } from "./IconBtnAdd/IconBtnAdd";
import { AnswerItem } from "./AnswerItem/AnswerItem";
import { TitleKeys, TQuestionEntity } from "../../IntegrationsModal";
const titleDictionary = {
contacts: "Контакты",
company: "Компании",
deal: "Сделки",
users: "Пользователи",
buyers: "Покупатели",
};
import {
TagKeys,
TitleKeys,
TQuestionEntity,
TTags,
} from "../../IntegrationsModal";
type ItemProps = {
title: TitleKeys;
title: TitleKeys | TagKeys;
onAddBtnClick: () => void;
questionEntity: TQuestionEntity;
data: TQuestionEntity | TTags;
};
export const Item: FC<ItemProps> = ({
title,
onAddBtnClick,
questionEntity,
}) => {
export const Item: FC<ItemProps> = ({ title, onAddBtnClick, data }) => {
const theme = useTheme();
const titleDictionary = {
contact: "Контакт",
company: "Компания",
deal: "Сделка",
buyer: "Покупатель",
contacts: "Контакты",
users: "Пользователи",
buyers: "Покупатели",
};
const translatedTitle = titleDictionary[title];
const questionEntityTexts = questionEntity[title];
const selectedOptions = data[title];
return (
<Box
sx={{
@ -50,8 +54,14 @@ export const Item: FC<ItemProps> = ({
{translatedTitle}
</Typography>
</Box>
{questionEntityTexts &&
questionEntityTexts.map((text) => <AnswerItem text={text} />)}
{selectedOptions &&
selectedOptions.map((text, index) => (
<AnswerItem
key={text + index}
fieldValue={"Значение поля"}
fieldName={text}
/>
))}
<IconBtnAdd onAddBtnClick={onAddBtnClick} />
</Box>

@ -1,4 +1,4 @@
import { Box } from "@mui/material";
import { Box, useTheme } from "@mui/material";
import { Item } from "../Item/Item";
import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock";
import { FC } from "react";
@ -21,6 +21,8 @@ export const ItemDetailsView: FC<ItemDetailsViewProps> = ({
setActiveItem,
setIsSelection,
}) => {
const theme = useTheme();
return (
<Box
sx={{
@ -28,34 +30,34 @@ export const ItemDetailsView: FC<ItemDetailsViewProps> = ({
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Box
sx={{
marginTop: "20px",
width: "100%",
height: "414px",
height: "400px",
flexGrow: 1,
borderRadius: "10px",
padding: "10px",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
display: "flex",
overflowY: "auto",
flexWrap: "wrap",
justifyContent: "start",
}}
>
{questionEntity &&
Object.keys(questionEntity).map((item) => (
<Item
key={item}
title={item}
title={item as TitleKeys}
onAddBtnClick={() => {
setIsSelection(true);
setActiveItem(item);
}}
questionEntity={questionEntity}
data={questionEntity}
/>
))}
</Box>

@ -1,47 +1,83 @@
import { Box, useMediaQuery, useTheme } from "@mui/material";
import { FC } from "react";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
import { useTheme } from "@mui/material";
import {
Dispatch,
FC,
SetStateAction,
useCallback,
useMemo,
useState,
} from "react";
import { TagKeys, TTags } from "../IntegrationsModal";
import Box from "@mui/material/Box";
import { ItemsSelectionView } from "../IntegrationStep6/ItemsSelectionView/ItemsSelectionView";
import { TagsDetailsView } from "./TagsDetailsView/TagsDetailsView";
type IntegrationStep7Props = {
handlePrevStep: () => void;
handleSmallBtn: () => void;
handleLargeBtn: () => void;
tags: TTags;
setTags: Dispatch<SetStateAction<TTags>>;
};
export const IntegrationStep7: FC<IntegrationStep7Props> = ({
handlePrevStep,
handleSmallBtn,
handleLargeBtn,
tags,
setTags,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
const [isSelection, setIsSelection] = useState<boolean>(false);
const [activeItem, setActiveItem] = useState<string | null>(null);
const [selectedValue, setSelectedValue] = useState<string | null>(null);
const handleAdd = useCallback(() => {
if (!activeItem || !selectedValue) return;
setTags((prevState) => ({
...prevState,
[activeItem]: [...prevState[activeItem as TagKeys], selectedValue],
}));
}, [activeItem, setTags, selectedValue]);
const items = useMemo(
() => ["#тег с результатом 1", "#еще один тег с результатом 2", "#тег"],
[],
);
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Box
sx={{
marginTop: "20px",
width: "100%",
height: "100%",
borderRadius: "10px",
padding: "10px",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
}}
></Box>
<Box
sx={{
marginTop: "20px",
alignSelf: "end",
}}
>
<StepButtonsBlock
onSmallBtnClick={handlePrevStep}
isLargeBtnMissing={true}
{isSelection ? (
<ItemsSelectionView
items={items}
selectedValue={selectedValue}
setSelectedValue={setSelectedValue}
onSmallBtnClick={() => {
setActiveItem(null);
setIsSelection(false);
}}
onLargeBtnClick={() => {
handleAdd();
setActiveItem(null);
setIsSelection(false);
}}
/>
</Box>
) : (
<TagsDetailsView
setIsSelection={setIsSelection}
handleLargeBtn={handleLargeBtn}
handleSmallBtn={handleSmallBtn}
tags={tags}
setActiveItem={setActiveItem}
/>
)}
</Box>
);
};

@ -0,0 +1,99 @@
import { Box, Typography, useTheme } from "@mui/material";
import { StepButtonsBlock } from "../../StepButtonsBlock/StepButtonsBlock";
import { FC } from "react";
import { TagKeys, TTags } from "../../IntegrationsModal";
import { Item } from "../../IntegrationStep6/Item/Item";
type TagsDetailsViewProps = {
setIsSelection: (value: boolean) => void;
handleSmallBtn: () => void;
handleLargeBtn: () => void;
tags: TTags;
setActiveItem: (value: string | null) => void;
};
export const TagsDetailsView: FC<TagsDetailsViewProps> = ({
handleSmallBtn,
handleLargeBtn,
tags,
setActiveItem,
setIsSelection,
}) => {
const theme = useTheme();
return (
<Box
sx={{
marginTop: "20px",
display: "flex",
flexDirection: "column",
alignItems: "center",
height: "100%",
flexGrow: 1,
}}
>
<Box
sx={{
width: "100%",
height: "400px",
flexGrow: 1,
borderRadius: "10px",
padding: "10px",
boxShadow: "0 0 20px rgba(0, 0, 0, 0.15)",
display: "flex",
}}
>
<Box
sx={{
padding: "0 40px",
borderRight: `1px solid ${theme.palette.background.default}`,
height: "100%",
display: "flex",
alignItems: "center",
}}
>
<Typography
sx={{ fontSize: "14px", color: theme.palette.grey2.main }}
>
Результат
</Typography>
</Box>
<Box
sx={{
width: "100%",
flexGrow: 1,
display: "flex",
overflowY: "auto",
flexWrap: "wrap",
justifyContent: "start",
}}
>
{tags &&
Object.keys(tags).map((item) => (
<Item
key={item}
title={item as TagKeys}
onAddBtnClick={() => {
setIsSelection(true);
setActiveItem(item);
}}
data={tags}
/>
))}
</Box>
</Box>
<Box
sx={{
marginTop: "20px",
alignSelf: "end",
}}
>
<StepButtonsBlock
onSmallBtnClick={handleSmallBtn}
onLargeBtnClick={handleLargeBtn}
largeBtnText={"Сохранить"}
/>
</Box>
</Box>
);
};

@ -21,6 +21,7 @@ import { SettingsBlock } from "./SettingsBlock/SettingsBlock";
import { IntegrationStep7 } from "./IntegrationStep7/IntegrationStep7";
export type TitleKeys = "contacts" | "company" | "deal" | "users" | "buyers";
export type TQuestionEntity = Record<TitleKeys, string[] | []>;
type IntegrationsModalProps = {
isModalOpen: boolean;
@ -28,6 +29,9 @@ type IntegrationsModalProps = {
companyName: string | null;
};
export type TagKeys = "contact" | "company" | "deal" | "buyer";
export type TTags = Record<TagKeys, string[] | []>;
export const IntegrationsModal: FC<IntegrationsModalProps> = ({
isModalOpen,
handleCloseModal,
@ -58,6 +62,12 @@ export const IntegrationsModal: FC<IntegrationsModalProps> = ({
users: [],
buyers: [],
});
const [tags, setTags] = useState<TTags>({
deal: [],
contact: [],
company: [],
buyer: [],
});
const handleNextStep = () => {
setStep((prevState) => prevState + 1);
@ -65,7 +75,10 @@ export const IntegrationsModal: FC<IntegrationsModalProps> = ({
const handlePrevStep = () => {
setStep((prevState) => prevState - 1);
};
console.log("questionEntity", questionEntity);
const handleSave = () => {
handleCloseModal();
setStep(1);
};
const steps = useMemo(
() => [
@ -146,7 +159,14 @@ export const IntegrationsModal: FC<IntegrationsModalProps> = ({
{
title: "Добавление тегов",
isSettingsAvailable: true,
component: <IntegrationStep7 handlePrevStep={handlePrevStep} />,
component: (
<IntegrationStep7
handleSmallBtn={handlePrevStep}
handleLargeBtn={handleSave}
tags={tags}
setTags={setTags}
/>
),
},
],
[
@ -157,6 +177,7 @@ export const IntegrationsModal: FC<IntegrationsModalProps> = ({
selectedStagePerformer,
selectedStage,
selectedDealPerformer,
tags,
],
);
@ -236,6 +257,8 @@ export const IntegrationsModal: FC<IntegrationsModalProps> = ({
selectedStagePerformer={selectedStagePerformer}
selectedStage={selectedStage}
utmFile={utmFile}
questionEntity={questionEntity}
tags={tags}
/>
</Box>
) : (

@ -96,6 +96,9 @@ export const IntegrationsModalTitle: FC<IntegrationsModalTitleProps> = ({
"& path": {
stroke: theme.palette.common.white,
},
"& circle": {
stroke: theme.palette.common.white,
},
},
"&:active": {
backgroundColor: "#581CA7",
@ -103,6 +106,9 @@ export const IntegrationsModalTitle: FC<IntegrationsModalTitleProps> = ({
"& path": {
stroke: theme.palette.common.white,
},
"& circle": {
stroke: theme.palette.common.white,
},
},
}}
>

@ -5,6 +5,7 @@ import { SettingItemHeader } from "./SettingItemHeader/SettingItemHeader";
import { ResponsiblePerson } from "./ResponsiblePerson/ResponsiblePerson";
import { SelectedParameter } from "./SelectedParameter/SelectedParameter";
import { FileBlock } from "../../IntegrationStep5/FileBlock/FileBlock";
import { TQuestionEntity, TTags } from "../../IntegrationsModal";
type SettingItemProps = {
step: number;
@ -17,6 +18,8 @@ type SettingItemProps = {
selectedDealPerformer: string | null;
selectedStage: string | null;
utmFile: File | null;
questionEntity: TQuestionEntity;
tags: TTags;
};
export const SettingItem: FC<SettingItemProps> = ({
@ -30,6 +33,8 @@ export const SettingItem: FC<SettingItemProps> = ({
selectedDealPerformer,
selectedStage,
utmFile,
questionEntity,
tags,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -73,6 +78,68 @@ export const SettingItem: FC<SettingItemProps> = ({
</Box>
);
}
if (step === 5) {
const isFilled = Object.values(questionEntity).some(
(array) => array.length > 0,
);
const status = isFilled ? "Заполнено" : "Не заполнено";
return (
<>
<Typography
sx={{
color: theme.palette.grey2.main,
fontSize: "18px",
fontWeight: 400,
margin: "10px 8px 0 0",
}}
display={"inline-block"}
>
Статус:
</Typography>
<Typography
sx={{
color: theme.palette.grey3.main,
fontSize: "18px",
fontWeight: 400,
}}
display={"inline"}
>
{status}
</Typography>
</>
);
}
if (step === 6) {
const isFilled = Object.values(tags).some((array) => array.length > 0);
const status = isFilled ? "Заполнено" : "Не заполнено";
return (
<>
<Typography
sx={{
color: theme.palette.grey2.main,
fontSize: "18px",
fontWeight: 400,
margin: "10px 8px 0 0",
}}
display={"inline-block"}
>
Статус:
</Typography>
<Typography
sx={{
color: theme.palette.grey3.main,
fontSize: "18px",
fontWeight: 400,
}}
display={"inline"}
>
{status}
</Typography>
</>
);
}
return null;
}, [
step,
@ -82,6 +149,8 @@ export const SettingItem: FC<SettingItemProps> = ({
selectedDealPerformer,
selectedStage,
utmFile,
questionEntity,
tags,
]);
return (

@ -2,6 +2,7 @@ import { FC } from "react";
import { Box, useMediaQuery, useTheme } from "@mui/material";
import { StepButtonsBlock } from "../StepButtonsBlock/StepButtonsBlock";
import { SettingItem } from "./SettingItem/SettingItem";
import { TQuestionEntity, TTags } from "../IntegrationsModal";
type SettingsBlockProps = {
stepTitles: string[];
@ -13,6 +14,8 @@ type SettingsBlockProps = {
selectedStage: string | null;
selectedDealPerformer: string | null;
utmFile: File | null;
questionEntity: TQuestionEntity;
tags: TTags;
};
export const SettingsBlock: FC<SettingsBlockProps> = ({
@ -25,6 +28,8 @@ export const SettingsBlock: FC<SettingsBlockProps> = ({
selectedDealPerformer,
selectedStage,
utmFile,
questionEntity,
tags,
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(600));
@ -64,6 +69,8 @@ export const SettingsBlock: FC<SettingsBlockProps> = ({
selectedDealPerformer={selectedDealPerformer}
selectedStage={selectedStage}
utmFile={utmFile}
questionEntity={questionEntity}
tags={tags}
/>
))}
</Box>