feat: deal card, deal status, deal new dates, indicator, hide navbar

This commit is contained in:
2024-09-30 08:52:21 +03:00
parent 31d2c86770
commit 99b71b9da9
15 changed files with 313 additions and 146 deletions

View File

@@ -25,7 +25,6 @@ export type { BaseEnumListSchema } from './models/BaseEnumListSchema';
export type { BaseEnumSchema } from './models/BaseEnumSchema'; export type { BaseEnumSchema } from './models/BaseEnumSchema';
export type { BaseMarketplaceSchema } from './models/BaseMarketplaceSchema'; export type { BaseMarketplaceSchema } from './models/BaseMarketplaceSchema';
export type { BaseShippingWarehouseSchema } from './models/BaseShippingWarehouseSchema'; export type { BaseShippingWarehouseSchema } from './models/BaseShippingWarehouseSchema';
export type { BillPaymentInfo } from './models/BillPaymentInfo';
export type { BillPaymentStatus } from './models/BillPaymentStatus'; export type { BillPaymentStatus } from './models/BillPaymentStatus';
export type { BillStatusUpdateRequest } from './models/BillStatusUpdateRequest'; export type { BillStatusUpdateRequest } from './models/BillStatusUpdateRequest';
export type { Body_upload_product_image } from './models/Body_upload_product_image'; export type { Body_upload_product_image } from './models/Body_upload_product_image';

View File

@@ -2,12 +2,11 @@
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
import type { BillPaymentInfo } from './BillPaymentInfo';
import type { BillPaymentStatus } from './BillPaymentStatus'; import type { BillPaymentStatus } from './BillPaymentStatus';
import type { NotificationChannel } from './NotificationChannel'; import type { NotificationChannel } from './NotificationChannel';
export type BillStatusUpdateRequest = { export type BillStatusUpdateRequest = {
listenerTransactionId: number; listenerTransactionId: number;
channel: NotificationChannel; channel: NotificationChannel;
info: (BillPaymentInfo | BillPaymentStatus); info: BillPaymentStatus;
}; };

View File

@@ -26,5 +26,7 @@ export type DealSchema = {
shippingWarehouse?: (ShippingWarehouseSchema | string | null); shippingWarehouse?: (ShippingWarehouseSchema | string | null);
billRequest?: (DealBillRequestSchema | null); billRequest?: (DealBillRequestSchema | null);
category?: (ServicePriceCategorySchema | null); category?: (ServicePriceCategorySchema | null);
deliveryDate?: (string | null);
receivingSlotDate?: (string | null);
}; };

View File

@@ -17,5 +17,7 @@ export type DealSummary = {
totalProducts: number; totalProducts: number;
shipmentWarehouseId: (number | null); shipmentWarehouseId: (number | null);
shipmentWarehouseName: (string | null); shipmentWarehouseName: (string | null);
deliveryDate?: (string | null);
receivingSlotDate?: (string | null);
}; };

View File

@@ -2,7 +2,7 @@
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
/*background-color: green;*/ flex: 1;
} }
.header { .header {

View File

@@ -12,7 +12,7 @@
padding-bottom: rem(5); padding-bottom: rem(5);
font-size: var(--mantine-font-size-sm); font-size: var(--mantine-font-size-sm);
flex-wrap: wrap; flex-wrap: wrap;
/*border-color: red;*/
@mixin light { @mixin light {
background-color: var(--mantine-color-gray-1); background-color: var(--mantine-color-gray-1);
} }

View File

@@ -8,14 +8,16 @@ import {
CopyButton, CopyButton,
Flex, Flex,
Image, Image,
Indicator,
IndicatorProps,
Popover, Popover,
rem, rem,
Text, Text,
} from "@mantine/core"; } from "@mantine/core";
import classNames from "classnames";
import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx"; import { useDealPageContext } from "../../../pages/LeadsPage/contexts/DealPageContext.tsx";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheck } from "@fortawesome/free-solid-svg-icons"; import { faCheck } from "@fortawesome/free-solid-svg-icons";
import { DealStatus } from "../../../shared/enums/DealStatus.ts";
type Props = { type Props = {
dealSummary: DealSummary; dealSummary: DealSummary;
@@ -28,120 +30,149 @@ const DealSummaryCard: FC<Props> = ({ dealSummary }) => {
setSelectedDeal(deal); setSelectedDeal(deal);
}); });
}; };
const getDeadlineTextColor = (deadline: string) => { const getIndicatorProps = (): IndicatorProps => {
// generate three colors, yellow for 1 day, red for 0 days, green for more than 1 day // check if deal status is less then in delivery and delivery_date - current date is less then 3 days, then show indicator
const deadlineDate = new Date(deadline); // and if current status is less then in_delivery, then show indicator
if (!dealSummary.deliveryDate)
return { disabled: true };
const deliveryDate = new Date(dealSummary.deliveryDate);
const currentDate = new Date(); const currentDate = new Date();
const diff = deadlineDate.getTime() - currentDate.getTime(); const diff = deliveryDate.getTime() - currentDate.getTime();
const diffDays = Math.ceil(diff / (1000 * 3600 * 24)); const diffDays = Math.ceil(diff / (1000 * 3600 * 24));
if (diffDays < 0) return "red.8"; // for past deadlines
if (diffDays === 1) { if (dealSummary.status < DealStatus.IN_DELIVERY) {
return "yellow.8"; // if less than 2 days left, show yellow, if less than 1 day left, show red
if (diffDays <= 2 && diffDays > 1) {
return {
color: "yellow",
};
}
if (diffDays <= 1) {
return {
color: "red",
};
}
return {
disabled: false,
};
} }
if (diffDays === 0) { return { disabled: true };
return "orange.8";
}
return "green.8";
}; };
return ( return (
<div <Indicator
onClick={() => onDealSummaryClick()} position={"top-end"}
className={styles["container"]}> withBorder
{...getIndicatorProps()}
>
<div <div
className={classNames( onClick={() => onDealSummaryClick()}
styles["flex-row"], className={styles["container"]}>
styles["flex-row-left"] <Flex direction={"column"} flex={1} gap={rem(3)}>
)}> <Flex justify={"space-between"}>
<div className={styles["flex-item"]}>
<Text <Text
size={"sm"} c={"gray.6"}
c={"gray.6"}> size={"xs"}
Клиент: {dealSummary.clientName}
</Text> >
</div> {dealSummary.clientName}
<div className={styles["flex-item"]}> </Text>
<Text </Flex>
size={"md"}
c={"blue.5"}> <Text c={"blue.5"} size={"sm"}>
{dealSummary.name} {dealSummary.name}
</Text> </Text>
{dealSummary.shipmentWarehouseName && ( <Flex
// align={"center"}
direction={"column"}
justify={"space-between"}
>
<Text <Text
size={"sm"} size={"sm"}
c={"gray.6"}> c={"gray.6"}>
{dealSummary.shipmentWarehouseName} {dealSummary.shipmentWarehouseName || "Склад не указан"}
</Text> </Text>
)} <Text
</div> c={"gray.6"}
<div className={styles["flex-item"]}> size={"sm"}
<Text >
size={"sm"} {dealSummary.totalPrice.toLocaleString("ru-RU")} руб,{" "}
c={"gray.6"}> </Text>
{dealSummary.totalPrice.toLocaleString("ru-RU")} руб,{" "} <Text
{dealSummary.totalProducts.toLocaleString("ru-RU")} тов. c={"gray.6"}
</Text> size={"sm"}>
</div> {dealSummary.totalProducts.toLocaleString("ru-RU")} тов.
</Text>
</Flex>
<Flex direction={"column"}>
{dealSummary.deliveryDate && (
<Text
c={"gray.6"}
size={"sm"}>
Доставка: {(new Date(dealSummary.deliveryDate)).toLocaleDateString("ru-RU")}
</Text>
)}
{dealSummary.receivingSlotDate && (
<Text
c={"gray.6"}
size={"sm"}>
Приемка: {(new Date(dealSummary.receivingSlotDate)).toLocaleDateString("ru-RU")}
</Text>
)}
</Flex>
<Flex align={"center"} justify={"space-between"}>
<CopyButton value={dealSummary.id.toString()}>
{({ copy, copied }) => (
<Popover
opened={copied}
withArrow>
<Popover.Target>
<div
onClick={e => {
e.stopPropagation();
copy();
}}
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)}>
<FontAwesomeIcon
bounce
style={{ animationIterationCount: 1 }}
icon={faCheck}
/>
<Text size={"xs"}>
ID сделки скопирован
</Text>
</Flex>
</Popover.Dropdown>
</Popover>
)}
</CopyButton>
<ActionIcon variant={"transparent"}>
<Image
src={dealSummary.baseMarketplace?.iconUrl || ""}
/>
</ActionIcon>
</Flex>
</Flex>
</div> </div>
<div </Indicator>
className={classNames(
styles["flex-row"],
styles["flex-row-right"]
)}>
<div className={styles["flex-item"]}>
<ActionIcon variant={"transparent"}>
<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)}
</Text>
</div>
<CopyButton value={"https://google.com"}>
{({ copy, copied }) => (
<Popover
opened={copied}
withArrow>
<Popover.Target>
<div
onClick={e => {
e.stopPropagation();
copy();
}}
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)}>
<FontAwesomeIcon
bounce
style={{ animationIterationCount: 1 }}
icon={faCheck}
/>
<Text size={"xs"}>
ID сделки скопирован
</Text>
</Flex>
</Popover.Dropdown>
</Popover>
)}
</CopyButton>
</div>
</div>
); );
}; };
export default DealSummaryCard; export default DealSummaryCard;

View File

@@ -0,0 +1,10 @@
.icon {
box-shadow: 3px 3px 20px 2px rgb(0 0 0 / 8%), -3px -3px 20px 2px rgba(0, 0, 0, 0.08);
@mixin dark {
background-color: #454545;
}
@mixin light {
background-color: #f1f6f8;
color: var(--mantine-color-dark-3);
}
}

View File

@@ -0,0 +1,52 @@
import { ActionIcon, Affix, AffixProps, rem, Transition } from "@mantine/core";
import { IconArrowRight } from "@tabler/icons-react";
import { useSelector } from "react-redux";
import { RootState, useAppDispatch } from "../../redux/store.ts";
import { setHideNavbar } from "../../features/uiSlice.ts";
import { FC } from "react";
import stylesCss from "./HideNavbarAffix.module.css";
type Props = AffixProps;
const HideNavbarAffix: FC<Props> = (props) => {
const uiState = useSelector((state: RootState) => state.ui);
const dispatch = useAppDispatch();
return (
<>
{/*{uiState.hideNavbar && (*/}
<Transition
transition={"slide-right"}
mounted={uiState.hideNavbar}
>
{styles => (
<Affix
style={styles}
position={{
top: "50%",
left: rem(20),
}}
{...props}
>
<ActionIcon
onClick={() => {
dispatch(setHideNavbar(false));
}}
className={stylesCss["icon"]}
// color={"#2d2d2d"}
radius="xl"
size={45}>
<IconArrowRight
stroke={1.5}
// size={30}
/>
</ActionIcon>
</Affix>)}
</Transition>
{/*)*/}
{/*}*/}
</>
);
};
export default HideNavbarAffix;

View File

@@ -1,14 +1,6 @@
import { Center, Flex, Image, rem, Stack, Tooltip, UnstyledButton, useMantineColorScheme } from "@mantine/core";
import { import {
Center, IconArrowLeft,
Flex,
Image,
rem,
Stack,
Tooltip,
UnstyledButton,
useMantineColorScheme,
} from "@mantine/core";
import {
IconBarcode, IconBarcode,
IconBox, IconBox,
IconBuildingWarehouse, IconBuildingWarehouse,
@@ -26,6 +18,7 @@ import classes from "./Navbar.module.css";
import { useAppDispatch } from "../../redux/store.ts"; import { useAppDispatch } from "../../redux/store.ts";
import { logout } from "../../features/authSlice.ts"; import { logout } from "../../features/authSlice.ts";
import { useNavigate, useRouterState } from "@tanstack/react-router"; import { useNavigate, useRouterState } from "@tanstack/react-router";
import { setHideNavbar } from "../../features/uiSlice.ts";
interface NavbarLinkProps { interface NavbarLinkProps {
icon: typeof IconHome2; icon: typeof IconHome2;
@@ -118,6 +111,7 @@ export function Navbar() {
}; };
const links = mockdata.map((link, index) => ( const links = mockdata.map((link, index) => (
<NavbarLink <NavbarLink
{...link} {...link}
index={index} index={index}
key={link.label} key={link.label}
@@ -130,7 +124,9 @@ export function Navbar() {
<nav className={classes.navbar}> <nav className={classes.navbar}>
<Flex <Flex
direction={"column"} direction={"column"}
align={"center"}
gap={rem(30)}> gap={rem(30)}>
<Center p={rem(5)}> <Center p={rem(5)}>
<Image <Image
flex={1} flex={1}
@@ -183,6 +179,15 @@ export function Navbar() {
icon={IconLogout} icon={IconLogout}
label="Выйти" label="Выйти"
/> />
<NavbarLink
icon={IconArrowLeft}
href={"#"}
index={-1}
label={"Свернуть"}
onClick={() => {
dispatch(setHideNavbar(true));
}}
/>
</Stack> </Stack>
</nav> </nav>
); );

View File

@@ -2,10 +2,12 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface UIState { interface UIState {
isLoading: boolean; isLoading: boolean;
hideNavbar: boolean;
} }
const initialState: UIState = { const initialState: UIState = {
isLoading: false, isLoading: false,
hideNavbar: false,
}; };
const uiSlice = createSlice({ const uiSlice = createSlice({
@@ -15,8 +17,11 @@ const uiSlice = createSlice({
setIsLoading: (state, action: PayloadAction<boolean>) => { setIsLoading: (state, action: PayloadAction<boolean>) => {
state.isLoading = action.payload; state.isLoading = action.payload;
}, },
setHideNavbar: (state, action: PayloadAction<boolean>) => {
state.hideNavbar = action.payload;
},
}, },
}); });
export default uiSlice.reducer; export default uiSlice.reducer;
export const { setIsLoading } = uiSlice.actions; export const { setIsLoading, setHideNavbar} = uiSlice.actions;

View File

@@ -25,10 +25,11 @@ import { ButtonCopyControlled } from "../../../../../components/ButtonCopyContro
import { useClipboard } from "@mantine/hooks"; import { useClipboard } from "@mantine/hooks";
import ButtonCopy from "../../../../../components/ButtonCopy/ButtonCopy.tsx"; import ButtonCopy from "../../../../../components/ButtonCopy/ButtonCopy.tsx";
import FileSaver from "file-saver"; import FileSaver from "file-saver";
import { getCurrentDateTimeForFilename } from "../../../../../shared/lib/date.ts"; import { dateWithoutTimezone, getCurrentDateTimeForFilename } from "../../../../../shared/lib/date.ts";
import { IconBarcode, IconPrinter } from "@tabler/icons-react"; import { IconBarcode, IconPrinter } from "@tabler/icons-react";
import styles from "../../../ui/LeadsPage.module.css"; import styles from "../../../ui/LeadsPage.module.css";
import { base64ToBlob } from "../../../../../shared/lib/utils.ts"; import { base64ToBlob } from "../../../../../shared/lib/utils.ts";
import { DatePickerInput } from "@mantine/dates";
type Props = { type Props = {
deal: DealSchema; deal: DealSchema;
@@ -41,7 +42,17 @@ const Content: FC<Props> = ({ deal }) => {
const clipboard = useClipboard(); const clipboard = useClipboard();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const initialValues: FormType = deal; // ignore typescript
const initialValues: FormType = {
...deal,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
deliveryDate: deal.deliveryDate ? new Date(deal.deliveryDate) : null,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
receivingSlotDate: deal.receivingSlotDate ? new Date(deal.receivingSlotDate) : null,
};
const form = useForm<FormType>({ const form = useForm<FormType>({
initialValues: initialValues, initialValues: initialValues,
validate: { validate: {
@@ -85,7 +96,14 @@ const Content: FC<Props> = ({ deal }) => {
await updateClientInfo(values); await updateClientInfo(values);
} }
// updating deal info // updating deal info
await updateDealInfo(values); // get shimpent warehouse name from object if its object, otherwise just pass it
const shippingWarehouse = isShippingWarehouse(values.shippingWarehouse) ? values.shippingWarehouse.name : values.shippingWarehouse;
await updateDealInfo({
...values,
deliveryDate: values.deliveryDate ? dateWithoutTimezone(new Date(values.deliveryDate)) : null,
receivingSlotDate: values.receivingSlotDate ? dateWithoutTimezone(new Date(values.receivingSlotDate)) : null,
shippingWarehouse: shippingWarehouse,
});
}; };
const isShippingWarehouse = ( const isShippingWarehouse = (
value: ShippingWarehouseSchema | string | null | undefined, value: ShippingWarehouseSchema | string | null | undefined,
@@ -171,6 +189,21 @@ const Content: FC<Props> = ({ deal }) => {
).onChange(event); ).onChange(event);
}} }}
/> />
<DatePickerInput
minDate={new Date()}
placeholder={"Укажите дату передачи в доставку"}
label={"Дата передачи в доставку"}
{...form.getInputProps("deliveryDate")}
/>
<DatePickerInput
minDate={new Date()}
placeholder={"Укажите слот приемки"}
label={"Слот приемки"}
{...form.getInputProps("receivingSlotDate")}
/>
</Flex> </Flex>
</Fieldset> </Fieldset>
<Flex <Flex

View File

@@ -8,7 +8,7 @@ import PageBlock from "../../../components/PageBlock/PageBlock.tsx";
import DealEditDrawer from "../drawers/DealEditDrawer/DealEditDrawer.tsx"; import DealEditDrawer from "../drawers/DealEditDrawer/DealEditDrawer.tsx";
import { DealPageContextProvider } from "../contexts/DealPageContext.tsx"; import { DealPageContextProvider } from "../contexts/DealPageContext.tsx";
import { modals } from "@mantine/modals"; import { modals } from "@mantine/modals";
import { DealService, DealSummary, DealSummaryReorderRequest } from "../../../client"; import { DealService, DealSummaryReorderRequest } from "../../../client";
import { ActionIcon, Flex, NumberInput, rem, Text } from "@mantine/core"; import { ActionIcon, Flex, NumberInput, rem, Text } from "@mantine/core";
import classNames from "classnames"; import classNames from "classnames";
import { notifications } from "../../../shared/lib/notifications.ts"; import { notifications } from "../../../shared/lib/notifications.ts";
@@ -19,6 +19,7 @@ import BaseMarketplaceSelect from "../../../components/Selects/BaseMarketplaceSe
import ClientSelectNew from "../../../components/Selects/ClientSelectNew/ClientSelectNew.tsx"; import ClientSelectNew from "../../../components/Selects/ClientSelectNew/ClientSelectNew.tsx";
import DealsTable from "../../DealsPage/components/DealsTable/DealsTable.tsx"; 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";
enum DisplayMode { enum DisplayMode {
BOARD, BOARD,
@@ -31,11 +32,11 @@ export const LeadsPage: FC = () => {
const { summariesRaw, refetch } = useDealSummaries(); const { summariesRaw, refetch } = useDealSummaries();
const [summaries, setSummaries] = useState(summariesRaw); const [summaries, setSummaries] = useState(summariesRaw);
const [displayMode, setDisplayMode] = useState<DisplayMode>( const [displayMode, setDisplayMode] = useState<DisplayMode>(
DisplayMode.BOARD DisplayMode.BOARD,
); );
const [isDragEnded, setIsDragEnded] = useState(true); const [isDragEnded, setIsDragEnded] = useState(true);
const [selectedDeals, setSelectedDeals] = useState<DealSummary[]>([]); // const [selectedDeals, setSelectedDeals] = useState<DealSummary[]>([]);
useEffect(() => { useEffect(() => {
setSummaries(summariesRaw); setSummaries(summariesRaw);
@@ -129,19 +130,18 @@ export const LeadsPage: FC = () => {
}); });
return; return;
} }
modals.openContextModal({
modal: "enterDeadline", DealService.reorderDealSummaries({
title: "Необходимо указать дедлайн", requestBody: {
innerProps: { dealId: dealId,
onSubmit: event => status: status,
DealService.reorderDealSummaries({ index: result.destination.index,
requestBody: event, comment: "",
}).then(async response => { deadline: dateWithoutTimezone(new Date()),
setSummaries(response.summaries);
await refetch();
}),
request: request,
}, },
}).then(async response => {
setSummaries(response.summaries);
await refetch();
}); });
}; };
const getTableBody = () => { const getTableBody = () => {
@@ -151,7 +151,9 @@ export const LeadsPage: FC = () => {
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ duration: 0.2 }}> transition={{ duration: 0.2 }}>
<DealsTable items={data} onSelectionChange={setSelectedDeals} /> <DealsTable items={data}
// onSelectionChange={setSelectedDeals}
/>
</motion.div> </motion.div>
); );
}; };
@@ -188,6 +190,15 @@ export const LeadsPage: FC = () => {
droppableId={"AWAITING_ACCEPTANCE"} droppableId={"AWAITING_ACCEPTANCE"}
color={"#4A90E2"} color={"#4A90E2"}
/> />
<Board
summaries={summaries.filter(
summary =>
summary.status == DealStatus.READY_FOR_WORK,
)}
title={"Готов к работе"}
droppableId={"READY_FOR_WORK"}
color={"#D3D3D3"}
/>
<Board <Board
summaries={summaries.filter( summaries={summaries.filter(
summary => summary =>
@@ -207,6 +218,15 @@ export const LeadsPage: FC = () => {
droppableId={"AWAITING_SHIPMENT"} droppableId={"AWAITING_SHIPMENT"}
color={"#7ED321"} color={"#7ED321"}
/> />
<Board
summaries={summaries.filter(
summary =>
summary.status == DealStatus.IN_DELIVERY,
)}
title={"В доставке"}
droppableId={"IN_DELIVERY"}
color={"#6A0DAD"}
/>
<Board <Board
summaries={summaries.filter( summaries={summaries.filter(
summary => summary =>

View File

@@ -4,12 +4,14 @@ import { useSelector } from "react-redux";
import { RootState } from "../../redux/store.ts"; import { RootState } from "../../redux/store.ts";
import styles from "./PageWrapper.module.css"; import styles from "./PageWrapper.module.css";
import { Navbar } from "../../components/Navbar/Navbar.tsx"; import { Navbar } from "../../components/Navbar/Navbar.tsx";
import HideNavbarAffix from "../../components/HideNavbarAffix/HideNavbarAffix.tsx";
export type Props = { export type Props = {
children: ReactNode; children: ReactNode;
}; };
const PageWrapper: FC<Props> = ({ children }) => { const PageWrapper: FC<Props> = ({ children }) => {
const authState = useSelector((state: RootState) => state.auth); const authState = useSelector((state: RootState) => state.auth);
const uiState = useSelector((state: RootState) => state.ui);
return ( return (
<AppShell <AppShell
layout={"alt"} layout={"alt"}
@@ -17,10 +19,12 @@ const PageWrapper: FC<Props> = ({ children }) => {
navbar={ navbar={
authState.isAuthorized && !authState.isGuest authState.isAuthorized && !authState.isGuest
? { ? {
width: "130px", width: "130px",
breakpoint: "sm", breakpoint: "sm",
} collapsed: { desktop: uiState.hideNavbar },
}
: undefined : undefined
}> }>
<AppShell.Navbar> <AppShell.Navbar>
{authState.isAuthorized && !authState.isGuest && ( {authState.isAuthorized && !authState.isGuest && (
@@ -42,6 +46,7 @@ const PageWrapper: FC<Props> = ({ children }) => {
} }
className={styles["main-container"]}> className={styles["main-container"]}>
<div className={styles["container"]}>{children}</div> <div className={styles["container"]}>{children}</div>
<HideNavbarAffix />
</AppShell.Main> </AppShell.Main>
</AppShell> </AppShell>
); );

View File

@@ -1,11 +1,13 @@
export enum DealStatus { export enum DealStatus {
CREATED = 0, CREATED = 0,
AWAITING_ACCEPTANCE = 1, AWAITING_ACCEPTANCE = 1,
PACKAGING = 2, READY_FOR_WORK = 2,
AWAITING_SHIPMENT = 3, PACKAGING = 3,
AWAITING_PAYMENT = 4, AWAITING_SHIPMENT = 4,
COMPLETED = 5, IN_DELIVERY = 5,
CANCELLED = 6, AWAITING_PAYMENT = 6,
COMPLETED = 7,
CANCELLED = 8,
} }
export const getDealStatusByName = (name: string): DealStatus => { export const getDealStatusByName = (name: string): DealStatus => {
@@ -14,8 +16,10 @@ export const getDealStatusByName = (name: string): DealStatus => {
export const DealStatusDictionary = { export const DealStatusDictionary = {
[DealStatus.CREATED]: "Создан", [DealStatus.CREATED]: "Создан",
[DealStatus.AWAITING_ACCEPTANCE]: "Ожидает приемки", [DealStatus.AWAITING_ACCEPTANCE]: "Ожидает приемки",
[DealStatus.READY_FOR_WORK]: "Готов к работе",
[DealStatus.PACKAGING]: "Упаковка", [DealStatus.PACKAGING]: "Упаковка",
[DealStatus.AWAITING_SHIPMENT]: "Ожидает отгрузки", [DealStatus.AWAITING_SHIPMENT]: "Ожидает отгрузки",
[DealStatus.IN_DELIVERY]: "В доставке",
[DealStatus.AWAITING_PAYMENT]: "Ожидает оплаты", [DealStatus.AWAITING_PAYMENT]: "Ожидает оплаты",
[DealStatus.COMPLETED]: "Завершена", [DealStatus.COMPLETED]: "Завершена",
[DealStatus.CANCELLED]: "Отменена", [DealStatus.CANCELLED]: "Отменена",
@@ -25,7 +29,7 @@ export type DealStatusType = {
name: string; name: string;
}; };
export const DealStatuses: DealStatusType[] = Object.entries( export const DealStatuses: DealStatusType[] = Object.entries(
DealStatusDictionary DealStatusDictionary,
).map(([key, value]) => { ).map(([key, value]) => {
return { id: parseInt(key), name: value }; return { id: parseInt(key), name: value };
}); });