refactor: removed constant sizes
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
.create-button {
|
.create-button {
|
||||||
padding: 11px 10px 12px 10px;
|
padding: 10px 10px 11px 10px;
|
||||||
border-bottom: 2px solid gray;
|
border-bottom: 2px solid gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ const CreateBoardButtonMobile = () => {
|
|||||||
<Box
|
<Box
|
||||||
onClick={startEditing}
|
onClick={startEditing}
|
||||||
className={styles["create-button"]}>
|
className={styles["create-button"]}>
|
||||||
<IconPlus size={22} />
|
<IconPlus />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
modalTitle={"Создание доски"}
|
modalTitle={"Создание доски"}
|
||||||
|
|||||||
@ -8,15 +8,9 @@ type Props = {
|
|||||||
board: BoardSchema;
|
board: BoardSchema;
|
||||||
startEditing: () => void;
|
startEditing: () => void;
|
||||||
isHovered?: boolean;
|
isHovered?: boolean;
|
||||||
menuIconSize?: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const BoardMenu: FC<Props> = ({
|
const BoardMenu: FC<Props> = ({ board, startEditing, isHovered = true }) => {
|
||||||
board,
|
|
||||||
startEditing,
|
|
||||||
isHovered = true,
|
|
||||||
menuIconSize = 16,
|
|
||||||
}) => {
|
|
||||||
const { selectedBoard, onDeleteBoard } = useBoardsContext();
|
const { selectedBoard, onDeleteBoard } = useBoardsContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -29,7 +23,7 @@ const BoardMenu: FC<Props> = ({
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
onClick={e => e.stopPropagation()}>
|
onClick={e => e.stopPropagation()}>
|
||||||
<IconDotsVertical size={menuIconSize} />
|
<IconDotsVertical />
|
||||||
</Box>
|
</Box>
|
||||||
</Menu.Target>
|
</Menu.Target>
|
||||||
<Menu.Dropdown>
|
<Menu.Dropdown>
|
||||||
|
|||||||
@ -1,26 +1,31 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IconPlus } from "@tabler/icons-react";
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
import { Box, Center, Stack } from "@mantine/core";
|
import { Box, Center, Group, Stack, Text } from "@mantine/core";
|
||||||
import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
|
import { useStatusesContext } from "@/app/deals/contexts/StatusesContext";
|
||||||
import InPlaceInput from "@/components/ui/InPlaceInput/InPlaceInput";
|
import InPlaceInput from "@/components/ui/InPlaceInput/InPlaceInput";
|
||||||
|
import useIsMobile from "@/hooks/useIsMobile";
|
||||||
import styles from "./CreateStatusButton.module.css";
|
import styles from "./CreateStatusButton.module.css";
|
||||||
|
|
||||||
const CreateStatusButton = () => {
|
const CreateStatusButton = () => {
|
||||||
const { onCreateStatus } = useStatusesContext();
|
const { onCreateStatus } = useStatusesContext();
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Box
|
<Box className={styles.container}>
|
||||||
ml={6}
|
|
||||||
className={styles.container}>
|
|
||||||
<InPlaceInput
|
<InPlaceInput
|
||||||
placeholder={"Название колонки"}
|
placeholder={"Название колонки"}
|
||||||
onComplete={onCreateStatus}
|
onComplete={onCreateStatus}
|
||||||
getChildren={startEditing => (
|
getChildren={startEditing => (
|
||||||
<Center
|
<Center
|
||||||
p={15}
|
p={"sm"}
|
||||||
onClick={() => startEditing()}>
|
onClick={() => startEditing()}>
|
||||||
<IconPlus size={20} />
|
<Group gap={"xs"} wrap={"nowrap"} align={"start"}>
|
||||||
|
<IconPlus />
|
||||||
|
{isMobile && (
|
||||||
|
<Text>Добавить</Text>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
modalTitle={"Создание колонки"}
|
modalTitle={"Создание колонки"}
|
||||||
|
|||||||
@ -27,54 +27,46 @@ const Funnel: FC = () => {
|
|||||||
} = useDealsAndStatusesDnd();
|
} = useDealsAndStatusesDnd();
|
||||||
|
|
||||||
const renderFunnelDnd = () => (
|
const renderFunnelDnd = () => (
|
||||||
<>
|
<FunnelDnd
|
||||||
<FunnelDnd
|
containers={sortedStatuses}
|
||||||
containers={sortedStatuses}
|
items={deals}
|
||||||
items={deals}
|
onDragStart={handleDragStart}
|
||||||
onDragStart={handleDragStart}
|
onDragOver={handleDragOver}
|
||||||
onDragOver={handleDragOver}
|
onDragEnd={handleDragEnd}
|
||||||
onDragEnd={handleDragEnd}
|
getContainerId={(status: StatusSchema) => `${status.id}-status`}
|
||||||
getContainerId={(status: StatusSchema) => `${status.id}-status`}
|
getItemsByContainer={(status: StatusSchema, items: DealSchema[]) =>
|
||||||
getItemsByContainer={(
|
sortByLexorank(
|
||||||
status: StatusSchema,
|
items.filter(deal => deal.statusId === status.id)
|
||||||
items: DealSchema[]
|
)
|
||||||
) =>
|
}
|
||||||
sortByLexorank(
|
renderContainer={(
|
||||||
items.filter(deal => deal.statusId === status.id)
|
status: StatusSchema,
|
||||||
)
|
funnelColumnComponent: ReactNode
|
||||||
}
|
) => (
|
||||||
renderContainer={(
|
<StatusColumnWrapper
|
||||||
status: StatusSchema,
|
status={status}
|
||||||
funnelColumnComponent: ReactNode
|
isDragging={activeStatus?.id === status.id}>
|
||||||
) => (
|
{funnelColumnComponent}
|
||||||
<StatusColumnWrapper
|
</StatusColumnWrapper>
|
||||||
status={status}
|
)}
|
||||||
isDragging={activeStatus?.id === status.id}>
|
renderItem={(deal: DealSchema) => (
|
||||||
{funnelColumnComponent}
|
<DealContainer
|
||||||
</StatusColumnWrapper>
|
key={deal.id}
|
||||||
)}
|
deal={deal}
|
||||||
renderItem={(deal: DealSchema) => (
|
/>
|
||||||
<DealContainer
|
)}
|
||||||
key={deal.id}
|
activeContainer={activeStatus}
|
||||||
deal={deal}
|
activeItem={activeDeal}
|
||||||
/>
|
renderItemOverlay={(deal: DealSchema) => <DealCard deal={deal} />}
|
||||||
)}
|
renderContainerOverlay={(status: StatusSchema, children) => (
|
||||||
activeContainer={activeStatus}
|
<StatusColumnWrapper
|
||||||
activeItem={activeDeal}
|
status={status}
|
||||||
renderItemOverlay={(deal: DealSchema) => (
|
isDragging>
|
||||||
<DealCard deal={deal} />
|
{children}
|
||||||
)}
|
</StatusColumnWrapper>
|
||||||
renderContainerOverlay={(status: StatusSchema, children) => (
|
)}
|
||||||
<StatusColumnWrapper
|
disabledColumns={isMobile}
|
||||||
status={status}
|
/>
|
||||||
isDragging>
|
|
||||||
{children}
|
|
||||||
</StatusColumnWrapper>
|
|
||||||
)}
|
|
||||||
disabledColumns={isMobile}
|
|
||||||
/>
|
|
||||||
{!isMobile && <CreateStatusButton />}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isMobile) return renderFunnelDnd();
|
if (isMobile) return renderFunnelDnd();
|
||||||
@ -86,8 +78,9 @@ const Funnel: FC = () => {
|
|||||||
<Group
|
<Group
|
||||||
align={"start"}
|
align={"start"}
|
||||||
wrap={"nowrap"}
|
wrap={"nowrap"}
|
||||||
gap={0}>
|
gap={"xs"}>
|
||||||
{renderFunnelDnd()}
|
{renderFunnelDnd()}
|
||||||
|
<CreateStatusButton />
|
||||||
</Group>
|
</Group>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,3 +7,7 @@
|
|||||||
width: 80vw;
|
width: 80vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
border-bottom: solid blue 3px;
|
||||||
|
}
|
||||||
|
|||||||
@ -27,12 +27,13 @@ const StatusColumnWrapper = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box className={styles.container}>
|
||||||
mx={7}
|
|
||||||
className={styles.container}>
|
|
||||||
<Group
|
<Group
|
||||||
justify={"space-between"}
|
justify={"space-between"}
|
||||||
className={"flex-nowrap border-b-3 border-blue-500 mb-3 p-3"}>
|
p={"sm"}
|
||||||
|
wrap={"nowrap"}
|
||||||
|
mb={"xs"}
|
||||||
|
className={styles.header}>
|
||||||
<InPlaceInput
|
<InPlaceInput
|
||||||
defaultValue={status.name}
|
defaultValue={status.name}
|
||||||
onComplete={value => handleSave(value)}
|
onComplete={value => handleSave(value)}
|
||||||
|
|||||||
@ -23,12 +23,11 @@ const StatusMenu: FC<Props> = ({ status, handleEdit }) => {
|
|||||||
<Menu>
|
<Menu>
|
||||||
<Menu.Target>
|
<Menu.Target>
|
||||||
<Box
|
<Box
|
||||||
p={5}
|
|
||||||
style={{
|
style={{
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
onClick={e => e.stopPropagation()}>
|
onClick={e => e.stopPropagation()}>
|
||||||
<IconDotsVertical size={16} />
|
<IconDotsVertical />
|
||||||
</Box>
|
</Box>
|
||||||
</Menu.Target>
|
</Menu.Target>
|
||||||
<Menu.Dropdown>
|
<Menu.Dropdown>
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const BoardStatusesEditorDrawer: FC = () => {
|
|||||||
|
|
||||||
const renderDraggable = () => (
|
const renderDraggable = () => (
|
||||||
<Box p={"xs"}>
|
<Box p={"xs"}>
|
||||||
<IconGripVertical size={22} />
|
<IconGripVertical />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,6 @@ const StatusMobile: FC<Props> = ({ status }) => {
|
|||||||
<BoardMenu
|
<BoardMenu
|
||||||
board={status}
|
board={status}
|
||||||
startEditing={startEditing}
|
startEditing={startEditing}
|
||||||
menuIconSize={22}
|
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const ProjectBoardsEditorDrawer: FC = () => {
|
|||||||
|
|
||||||
const renderDraggable = () => (
|
const renderDraggable = () => (
|
||||||
<Box p={"xs"}>
|
<Box p={"xs"}>
|
||||||
<IconGripVertical size={22} />
|
<IconGripVertical />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,9 @@ import styles from "./../ProjectsEditorDrawer.module.css";
|
|||||||
type Props = {
|
type Props = {
|
||||||
project: ProjectSchema;
|
project: ProjectSchema;
|
||||||
startEditing: () => void;
|
startEditing: () => void;
|
||||||
menuIconSize: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProjectMenu: FC<Props> = ({
|
const ProjectMenu: FC<Props> = ({ project, startEditing }) => {
|
||||||
project,
|
|
||||||
startEditing,
|
|
||||||
menuIconSize = 16,
|
|
||||||
}) => {
|
|
||||||
const { onDeleteProject } = useProjectsContext();
|
const { onDeleteProject } = useProjectsContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -24,7 +19,7 @@ const ProjectMenu: FC<Props> = ({
|
|||||||
<Box
|
<Box
|
||||||
className={styles["menu-button"]}
|
className={styles["menu-button"]}
|
||||||
onClick={e => e.stopPropagation()}>
|
onClick={e => e.stopPropagation()}>
|
||||||
<IconDotsVertical size={menuIconSize} />
|
<IconDotsVertical />
|
||||||
</Box>
|
</Box>
|
||||||
</Menu.Target>
|
</Menu.Target>
|
||||||
<Menu.Dropdown>
|
<Menu.Dropdown>
|
||||||
|
|||||||
@ -46,7 +46,6 @@ const ProjectMobile: FC<Props> = ({ project }) => {
|
|||||||
<ProjectMenu
|
<ProjectMenu
|
||||||
project={project}
|
project={project}
|
||||||
startEditing={startEditing}
|
startEditing={startEditing}
|
||||||
menuIconSize={22}
|
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -69,7 +69,7 @@ const FunnelDnd = <
|
|||||||
containers.map(container => {
|
containers.map(container => {
|
||||||
const containerItems = getItemsByContainer(container, items);
|
const containerItems = getItemsByContainer(container, items);
|
||||||
const containerId = getContainerId(container);
|
const containerId = getContainerId(container);
|
||||||
return (
|
const item = (
|
||||||
<SortableItem
|
<SortableItem
|
||||||
key={containerId}
|
key={containerId}
|
||||||
id={containerId}
|
id={containerId}
|
||||||
@ -86,11 +86,13 @@ const FunnelDnd = <
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
if (!isMobile) return item;
|
||||||
|
return <Carousel.Slide key={containerId}>{item}</Carousel.Slide>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderBody = () => (
|
const renderBody = () => {
|
||||||
<>
|
if (isMobile) {
|
||||||
{isMobile ? (
|
return (
|
||||||
<Carousel
|
<Carousel
|
||||||
slideSize={"80%"}
|
slideSize={"80%"}
|
||||||
slideGap={"md"}
|
slideGap={"md"}
|
||||||
@ -101,31 +103,17 @@ const FunnelDnd = <
|
|||||||
{renderContainers()}
|
{renderContainers()}
|
||||||
<CreateStatusButton />
|
<CreateStatusButton />
|
||||||
</Carousel>
|
</Carousel>
|
||||||
) : (
|
);
|
||||||
renderContainers()
|
}
|
||||||
)}
|
return (
|
||||||
<FunnelOverlay
|
<Group
|
||||||
activeContainer={activeContainer}
|
gap={"xs"}
|
||||||
activeItem={activeItem}
|
wrap="nowrap"
|
||||||
renderContainer={container => {
|
align="start">
|
||||||
const containerItems = getItemsByContainer(
|
{renderContainers()}
|
||||||
container,
|
</Group>
|
||||||
items
|
);
|
||||||
);
|
};
|
||||||
const containerId = getContainerId(container);
|
|
||||||
return renderContainerOverlay(
|
|
||||||
container,
|
|
||||||
<FunnelColumn
|
|
||||||
id={containerId}
|
|
||||||
items={containerItems}
|
|
||||||
renderItem={renderItem}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
renderItem={renderItemOverlay}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DndContext
|
<DndContext
|
||||||
@ -137,16 +125,27 @@ const FunnelDnd = <
|
|||||||
<SortableContext
|
<SortableContext
|
||||||
items={containers.map(getContainerId)}
|
items={containers.map(getContainerId)}
|
||||||
strategy={horizontalListSortingStrategy}>
|
strategy={horizontalListSortingStrategy}>
|
||||||
{isMobile ? (
|
{renderBody()}
|
||||||
renderBody()
|
<FunnelOverlay
|
||||||
) : (
|
activeContainer={activeContainer}
|
||||||
<Group
|
activeItem={activeItem}
|
||||||
gap={0}
|
renderContainer={container => {
|
||||||
wrap="nowrap"
|
const containerItems = getItemsByContainer(
|
||||||
align="start">
|
container,
|
||||||
{renderBody()}
|
items
|
||||||
</Group>
|
);
|
||||||
)}
|
const containerId = getContainerId(container);
|
||||||
|
return renderContainerOverlay(
|
||||||
|
container,
|
||||||
|
<FunnelColumn
|
||||||
|
id={containerId}
|
||||||
|
items={containerItems}
|
||||||
|
renderItem={renderItem}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
renderItem={renderItemOverlay}
|
||||||
|
/>
|
||||||
</SortableContext>
|
</SortableContext>
|
||||||
</DndContext>
|
</DndContext>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user