feat: prettier
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/*background-color: green;*/
|
||||
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -34,7 +33,6 @@
|
||||
}
|
||||
@mixin dark {
|
||||
background-color: var(--mantine-color-dark-5);
|
||||
|
||||
}
|
||||
border-radius: var(--item-border-radius);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {FC} from "react";
|
||||
import styles from './Board.module.css';
|
||||
import {Divider, Text, Title} from '@mantine/core';
|
||||
import {Draggable, Droppable} from "@hello-pangea/dnd";
|
||||
import { FC } from "react";
|
||||
import styles from "./Board.module.css";
|
||||
import { Divider, Text, Title } from "@mantine/core";
|
||||
import { Draggable, Droppable } from "@hello-pangea/dnd";
|
||||
import CreateDealButton from "../CreateDealButton/CreateDealButton.tsx";
|
||||
import {DealSummary} from "../../../client";
|
||||
import { DealSummary } from "../../../client";
|
||||
import DealSummaryCard from "../DealSummaryCard/DealSummaryCard.tsx";
|
||||
import classNames from "classnames";
|
||||
import {getPluralForm} from "../../../shared/lib/utils.ts";
|
||||
import {sum} from "lodash";
|
||||
import { getPluralForm } from "../../../shared/lib/utils.ts";
|
||||
import { sum } from "lodash";
|
||||
|
||||
type Props = {
|
||||
droppableId: string;
|
||||
@@ -15,66 +15,74 @@ type Props = {
|
||||
withCreateButton?: boolean;
|
||||
summaries: DealSummary[];
|
||||
color: string;
|
||||
}
|
||||
};
|
||||
|
||||
export const Board: FC<Props> = ({droppableId, title, summaries, color, withCreateButton = false}) => {
|
||||
export const Board: FC<Props> = ({
|
||||
droppableId,
|
||||
title,
|
||||
summaries,
|
||||
color,
|
||||
withCreateButton = false,
|
||||
}) => {
|
||||
const getDealsText = () => {
|
||||
const pluralForm = getPluralForm(summaries.length, 'сделка', 'сделки', 'сделок');
|
||||
const pluralForm = getPluralForm(
|
||||
summaries.length,
|
||||
"сделка",
|
||||
"сделки",
|
||||
"сделок"
|
||||
);
|
||||
return `${summaries.length} ${pluralForm}: ${sum(summaries.map(summary => summary.totalPrice)).toLocaleString("ru-RU")}₽`;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles["container"]}>
|
||||
<div className={styles["header"]}>
|
||||
<Title size={"h4"}>{title}</Title>
|
||||
<Text>{getDealsText()}</Text>
|
||||
<Divider size={"xl"} my={10} color={color}/>
|
||||
<Divider
|
||||
size={"xl"}
|
||||
my={10}
|
||||
color={color}
|
||||
/>
|
||||
</div>
|
||||
<Droppable
|
||||
droppableId={droppableId}
|
||||
>
|
||||
<Droppable droppableId={droppableId}>
|
||||
{(provided, snapshot) => (
|
||||
<div ref={provided.innerRef}
|
||||
className={classNames(
|
||||
styles["items-list"],
|
||||
(snapshot.isDraggingOver && !snapshot.draggingFromThisWith)
|
||||
&& styles["items-list-drag-over"]
|
||||
)}
|
||||
{...provided.droppableProps}
|
||||
>
|
||||
{withCreateButton &&
|
||||
<CreateDealButton
|
||||
|
||||
onClick={() => {
|
||||
}}
|
||||
/>}
|
||||
{summaries.map(summary =>
|
||||
(
|
||||
<Draggable
|
||||
draggableId={summary.id.toString()}
|
||||
index={summary.rank}
|
||||
key={summary.id}
|
||||
>
|
||||
{(provided) => (
|
||||
<div {...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
|
||||
>
|
||||
<DealSummaryCard dealSummary={summary}/>
|
||||
</div>
|
||||
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
className={classNames(
|
||||
styles["items-list"],
|
||||
snapshot.isDraggingOver &&
|
||||
!snapshot.draggingFromThisWith &&
|
||||
styles["items-list-drag-over"]
|
||||
)}
|
||||
{...provided.droppableProps}>
|
||||
{withCreateButton && (
|
||||
<CreateDealButton onClick={() => {}} />
|
||||
)}
|
||||
{summaries.map(summary => (
|
||||
<Draggable
|
||||
draggableId={summary.id.toString()}
|
||||
index={summary.rank}
|
||||
key={summary.id}>
|
||||
{provided => (
|
||||
<div
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}>
|
||||
<DealSummaryCard
|
||||
dealSummary={summary}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Board;
|
||||
export default Board;
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
border: dashed var(--item-border-size) var(--mantine-color-default-border);
|
||||
border-radius: var(--item-border-radius);
|
||||
cursor: pointer;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.container:hover {
|
||||
background-color: light-dark(var(--mantine-color-default-hover), var(--mantine-color-gray-filled-hover));
|
||||
|
||||
}
|
||||
background-color: light-dark(
|
||||
var(--mantine-color-default-hover),
|
||||
var(--mantine-color-gray-filled-hover)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,60 +1,61 @@
|
||||
import {FC, useState} from "react";
|
||||
import { FC, useState } from "react";
|
||||
|
||||
import styles from './CreateDealButton.module.css';
|
||||
import {Text, Transition} from '@mantine/core';
|
||||
import styles from "./CreateDealButton.module.css";
|
||||
import { Text, Transition } from "@mantine/core";
|
||||
import CreateDealFrom from "../CreateDealForm/CreateDealFrom.tsx";
|
||||
import {DealService} from "../../../client";
|
||||
import {useQueryClient} from "@tanstack/react-query";
|
||||
import {dateWithoutTimezone} from "../../../shared/lib/date.ts";
|
||||
import { DealService } from "../../../client";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { dateWithoutTimezone } from "../../../shared/lib/date.ts";
|
||||
|
||||
type Props = {
|
||||
onClick: () => void;
|
||||
}
|
||||
};
|
||||
const CreateDealButton: FC<Props> = () => {
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [isTransitionEnded, setIsTransitionEnded] = useState(true);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return (
|
||||
<div className={styles['container']}
|
||||
onClick={() => {
|
||||
if (isCreating) return;
|
||||
setIsCreating(prevState => !prevState)
|
||||
setIsTransitionEnded(false);
|
||||
}}
|
||||
>
|
||||
{(!isCreating && isTransitionEnded) &&
|
||||
<div
|
||||
className={styles["container"]}
|
||||
onClick={() => {
|
||||
if (isCreating) return;
|
||||
setIsCreating(prevState => !prevState);
|
||||
setIsTransitionEnded(false);
|
||||
}}>
|
||||
{!isCreating && isTransitionEnded && (
|
||||
<Text>Быстрое добавление</Text>
|
||||
}
|
||||
)}
|
||||
<Transition
|
||||
mounted={isCreating}
|
||||
transition={"scale-y"}
|
||||
onExited={() => setIsTransitionEnded(true)}
|
||||
|
||||
>
|
||||
{(styles) => (
|
||||
onExited={() => setIsTransitionEnded(true)}>
|
||||
{styles => (
|
||||
<div style={styles}>
|
||||
<CreateDealFrom
|
||||
onCancel={() => {
|
||||
setIsCreating(false)
|
||||
setIsCreating(false);
|
||||
}}
|
||||
onSubmit={(quickDeal) => {
|
||||
onSubmit={quickDeal => {
|
||||
DealService.quickCreateDealQuickCreatePost({
|
||||
requestBody: {
|
||||
...quickDeal,
|
||||
acceptanceDate: dateWithoutTimezone(quickDeal.acceptanceDate)
|
||||
}
|
||||
acceptanceDate: dateWithoutTimezone(
|
||||
quickDeal.acceptanceDate
|
||||
),
|
||||
},
|
||||
}).then(async () => {
|
||||
await queryClient.invalidateQueries({queryKey: ['getDealSummaries']});
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ["getDealSummaries"],
|
||||
});
|
||||
setIsCreating(false);
|
||||
})
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Transition>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default CreateDealButton;
|
||||
);
|
||||
};
|
||||
export default CreateDealButton;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.inputs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inputs * {
|
||||
@@ -12,4 +12,3 @@
|
||||
display: flex;
|
||||
gap: rem(10);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,15 +5,14 @@ import { useForm } from "@mantine/form";
|
||||
import styles from "./CreateDealForm.module.css";
|
||||
import ClientAutocomplete from "../../Selects/ClientAutocomplete/ClientAutocomplete.tsx";
|
||||
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 ServicePriceCategorySelect from "../../Selects/ServicePriceCategorySelect/ServicePriceCategorySelect.tsx";
|
||||
|
||||
type Props = {
|
||||
onSubmit: (quickDeal: QuickDeal) => void
|
||||
onSubmit: (quickDeal: QuickDeal) => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
};
|
||||
const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => {
|
||||
const form = useForm<QuickDeal>({
|
||||
initialValues: {
|
||||
@@ -33,15 +32,15 @@ const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => {
|
||||
return (
|
||||
<form
|
||||
style={{ width: "100%" }}
|
||||
onSubmit={form.onSubmit((values) => onSubmit(values))}
|
||||
>
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
gap: rem(10),
|
||||
padding: rem(10),
|
||||
}}>
|
||||
onSubmit={form.onSubmit(values => onSubmit(values))}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
gap: rem(10),
|
||||
padding: rem(10),
|
||||
}}>
|
||||
<div className={styles["inputs"]}>
|
||||
<TextInput
|
||||
placeholder={"Название сделки"}
|
||||
@@ -63,7 +62,6 @@ const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => {
|
||||
{...form.getInputProps("shippingWarehouse")}
|
||||
placeholder={"Склад отгрузки"}
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div className={styles["inputs"]}>
|
||||
<ServicePriceCategorySelect
|
||||
@@ -89,20 +87,17 @@ const CreateDealFrom: FC<Props> = ({ onSubmit, onCancel }) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className={styles["buttons"]}>
|
||||
<Button
|
||||
type={"submit"}
|
||||
>Добавить</Button>
|
||||
<Button type={"submit"}>Добавить</Button>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
onClick={() => onCancel()}
|
||||
>Отменить</Button>
|
||||
onClick={() => onCancel()}>
|
||||
Отменить
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateDealFrom;
|
||||
export default CreateDealFrom;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
@mixin dark {
|
||||
background-color: var(--mantine-color-dark-5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.flex-row-left {
|
||||
@@ -27,13 +26,11 @@
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flex-row-right {
|
||||
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,109 +1,147 @@
|
||||
import {FC} from "react";
|
||||
import {DealService, DealSummary} from "../../../client";
|
||||
import styles from './DealSummaryCard.module.css';
|
||||
import { FC } from "react";
|
||||
import { DealService, DealSummary } from "../../../client";
|
||||
import styles from "./DealSummaryCard.module.css";
|
||||
|
||||
import {ActionIcon, Badge, CopyButton, Flex, Image, Popover, rem, Text} from '@mantine/core';
|
||||
import {
|
||||
ActionIcon,
|
||||
Badge,
|
||||
CopyButton,
|
||||
Flex,
|
||||
Image,
|
||||
Popover,
|
||||
rem,
|
||||
Text,
|
||||
} from "@mantine/core";
|
||||
import classNames from "classnames";
|
||||
import {useDealPageContext} from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faCheck} from "@fortawesome/free-solid-svg-icons";
|
||||
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
type Props = {
|
||||
dealSummary: DealSummary
|
||||
}
|
||||
dealSummary: DealSummary;
|
||||
};
|
||||
|
||||
const DealSummaryCard: FC<Props> = ({dealSummary}) => {
|
||||
const {setSelectedDeal} = useDealPageContext();
|
||||
const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
|
||||
const { setSelectedDeal } = useDealPageContext();
|
||||
const onDealSummaryClick = () => {
|
||||
DealService.getDealById({dealId: dealSummary.id})
|
||||
.then((deal) => {
|
||||
setSelectedDeal(deal);
|
||||
})
|
||||
}
|
||||
DealService.getDealById({ dealId: dealSummary.id }).then(deal => {
|
||||
setSelectedDeal(deal);
|
||||
});
|
||||
};
|
||||
const getDeadlineTextColor = (deadline: string) => {
|
||||
// generate three colors, yellow for 1 day, red for 0 days, green for more than 1 day
|
||||
const deadlineDate = new Date(deadline);
|
||||
const currentDate = new Date();
|
||||
const diff = deadlineDate.getTime() - currentDate.getTime();
|
||||
const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
|
||||
if (diffDays < 0)
|
||||
return 'red.8'; // for past deadlines
|
||||
if (diffDays < 0) return "red.8"; // for past deadlines
|
||||
if (diffDays === 1) {
|
||||
return 'yellow.8';
|
||||
return "yellow.8";
|
||||
}
|
||||
if (diffDays === 0) {
|
||||
return 'orange.8';
|
||||
return "orange.8";
|
||||
}
|
||||
return 'green.8';
|
||||
}
|
||||
return "green.8";
|
||||
};
|
||||
return (
|
||||
<div onClick={() => onDealSummaryClick()} className={styles['container']}>
|
||||
<div className={classNames(styles['flex-row'], styles["flex-row-left"])}>
|
||||
|
||||
<div className={styles['flex-item']}>
|
||||
<Text size={"sm"} c={"gray.6"}>
|
||||
<div
|
||||
onClick={() => onDealSummaryClick()}
|
||||
className={styles["container"]}>
|
||||
<div
|
||||
className={classNames(
|
||||
styles["flex-row"],
|
||||
styles["flex-row-left"]
|
||||
)}>
|
||||
<div className={styles["flex-item"]}>
|
||||
<Text
|
||||
size={"sm"}
|
||||
c={"gray.6"}>
|
||||
Клиент: {dealSummary.clientName}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={styles['flex-item']}>
|
||||
<Text size={"md"} c={"blue.5"}>{dealSummary.name}</Text>
|
||||
{dealSummary.shipmentWarehouseName &&
|
||||
<Text size={"sm"} c={"gray.6"}>{dealSummary.shipmentWarehouseName}</Text>
|
||||
}
|
||||
<div className={styles["flex-item"]}>
|
||||
<Text
|
||||
size={"md"}
|
||||
c={"blue.5"}>
|
||||
{dealSummary.name}
|
||||
</Text>
|
||||
{dealSummary.shipmentWarehouseName && (
|
||||
<Text
|
||||
size={"sm"}
|
||||
c={"gray.6"}>
|
||||
{dealSummary.shipmentWarehouseName}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles['flex-item']}>
|
||||
<Text size={"sm"} c={"gray.6"}>
|
||||
{dealSummary.totalPrice.toLocaleString('ru-RU')} руб, {dealSummary.totalProducts.toLocaleString("ru-RU")} тов.
|
||||
<div className={styles["flex-item"]}>
|
||||
<Text
|
||||
size={"sm"}
|
||||
c={"gray.6"}>
|
||||
{dealSummary.totalPrice.toLocaleString("ru-RU")} руб,{" "}
|
||||
{dealSummary.totalProducts.toLocaleString("ru-RU")} тов.
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
className={classNames(styles['flex-row'], styles['flex-row-right'])}>
|
||||
<div className={styles['flex-item']}>
|
||||
className={classNames(
|
||||
styles["flex-row"],
|
||||
styles["flex-row-right"]
|
||||
)}>
|
||||
<div className={styles["flex-item"]}>
|
||||
<ActionIcon variant={"transparent"}>
|
||||
<Image src={dealSummary.baseMarketplace?.iconUrl || ""}/>
|
||||
<Image
|
||||
src={dealSummary.baseMarketplace?.iconUrl || ""}
|
||||
/>
|
||||
</ActionIcon>
|
||||
</div>
|
||||
<div className={styles['flex-item']}>
|
||||
<Text size={"sm"} c={getDeadlineTextColor(dealSummary.deadline)}>
|
||||
{new Date(dealSummary.deadline).toLocaleString('ru-RU').slice(0, -3)}
|
||||
<div className={styles["flex-item"]}>
|
||||
<Text
|
||||
size={"sm"}
|
||||
c={getDeadlineTextColor(dealSummary.deadline)}>
|
||||
{new Date(dealSummary.deadline)
|
||||
.toLocaleString("ru-RU")
|
||||
.slice(0, -3)}
|
||||
</Text>
|
||||
</div>
|
||||
<CopyButton value={"https://google.com"}>
|
||||
{({copy, copied}) => (
|
||||
<Popover opened={copied} withArrow>
|
||||
{({ copy, copied }) => (
|
||||
<Popover
|
||||
opened={copied}
|
||||
withArrow>
|
||||
<Popover.Target>
|
||||
<div
|
||||
|
||||
onClick={(e) => {
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
copy();
|
||||
}}
|
||||
className={styles['flex-item']}>
|
||||
<Badge variant={"light"} radius={"sm"}>
|
||||
className={styles["flex-item"]}>
|
||||
<Badge
|
||||
variant={"light"}
|
||||
radius={"sm"}>
|
||||
ID: {dealSummary.id}
|
||||
</Badge>
|
||||
</div>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown>
|
||||
<Flex justify={"center"} align={"center"} gap={rem(5)}>
|
||||
<Flex
|
||||
justify={"center"}
|
||||
align={"center"}
|
||||
gap={rem(5)}>
|
||||
<FontAwesomeIcon
|
||||
bounce
|
||||
style={{animationIterationCount: 1}}
|
||||
style={{ animationIterationCount: 1 }}
|
||||
icon={faCheck}
|
||||
/>
|
||||
<Text size={"xs"}>ID сделки скопирован</Text>
|
||||
<Text size={"xs"}>
|
||||
ID сделки скопирован
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
)}
|
||||
</CopyButton>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
export default DealSummaryCard;
|
||||
|
||||
Reference in New Issue
Block a user