278 refactor uiboard opportunitiesboard + put state in recoil (#280)
* refactor: move Board file to opportunities * refactor: dropable props are move in ui component * refactor: rename provided in droppableProvided * refactor: rename provided in draggableProvided * refactor: rename BoardCard in BoardItem * refactor: rename BoardCard in BoardItem file * refactor: BoardItem use children instead of content * refactor: Extract StyledColumnContainer * refactor: create method to get optimistic new board after update * refactor: move getOptimisticNewBoard in board UI * refactor: make provided nullable * lint: remove unused import
This commit is contained in:
76
front/src/modules/opportunities/components/Board.tsx
Normal file
76
front/src/modules/opportunities/components/Board.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import {
|
||||
DragDropContext,
|
||||
Draggable,
|
||||
Droppable,
|
||||
OnDragEndResponder,
|
||||
} from '@hello-pangea/dnd';
|
||||
|
||||
import {
|
||||
Column,
|
||||
getOptimisticlyUpdatedBoard,
|
||||
Items,
|
||||
StyledBoard,
|
||||
} from '../../ui/components/board/Board';
|
||||
import {
|
||||
ItemsContainer,
|
||||
StyledColumn,
|
||||
StyledColumnTitle,
|
||||
} from '../../ui/components/board/BoardColumn';
|
||||
// Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd
|
||||
// https://github.com/atlassian/react-beautiful-dnd/issues/2350
|
||||
import { BoardItem } from '../../ui/components/board/BoardItem';
|
||||
import { NewButton } from '../../ui/components/board/BoardNewButton';
|
||||
|
||||
type BoardProps = {
|
||||
initialBoard: Column[];
|
||||
items: Items;
|
||||
};
|
||||
|
||||
export const Board = ({ initialBoard, items }: BoardProps) => {
|
||||
const [board, setBoard] = useState<Column[]>(initialBoard);
|
||||
|
||||
const onDragEnd: OnDragEndResponder = useCallback(
|
||||
(result) => {
|
||||
const newBoard = getOptimisticlyUpdatedBoard(board, result);
|
||||
if (!newBoard) return;
|
||||
setBoard(newBoard);
|
||||
// TODO implement update board mutation
|
||||
},
|
||||
[board],
|
||||
);
|
||||
|
||||
return (
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<StyledBoard>
|
||||
{board.map((column) => (
|
||||
<Droppable key={column.id} droppableId={column.id}>
|
||||
{(droppableProvided) => (
|
||||
<StyledColumn>
|
||||
<StyledColumnTitle color={column.colorCode}>
|
||||
• {column.title}
|
||||
</StyledColumnTitle>
|
||||
<ItemsContainer droppableProvided={droppableProvided}>
|
||||
{column.itemKeys.map((itemKey, index) => (
|
||||
<Draggable
|
||||
key={itemKey}
|
||||
draggableId={itemKey}
|
||||
index={index}
|
||||
>
|
||||
{(draggableProvided) => (
|
||||
<BoardItem draggableProvided={draggableProvided}>
|
||||
<p>{items[itemKey].content}</p>
|
||||
</BoardItem>
|
||||
)}
|
||||
</Draggable>
|
||||
))}
|
||||
</ItemsContainer>
|
||||
<NewButton />
|
||||
</StyledColumn>
|
||||
)}
|
||||
</Droppable>
|
||||
))}
|
||||
</StyledBoard>
|
||||
</DragDropContext>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,22 @@
|
||||
import { StrictMode } from 'react';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Board } from '../Board';
|
||||
|
||||
import { initialBoard, items } from './mock-data';
|
||||
|
||||
const meta: Meta<typeof Board> = {
|
||||
title: 'UI/Board/Board',
|
||||
component: Board,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Board>;
|
||||
|
||||
export const OneColumnBoard: Story = {
|
||||
render: () => (
|
||||
<StrictMode>
|
||||
<Board initialBoard={initialBoard} items={items} />
|
||||
</StrictMode>
|
||||
),
|
||||
};
|
||||
@ -0,0 +1,55 @@
|
||||
import { Column, Items } from '../../../ui/components/board/Board';
|
||||
|
||||
export const items: Items = {
|
||||
'item-1': { id: 'item-1', content: 'Item 1' },
|
||||
'item-2': { id: 'item-2', content: 'Item 2' },
|
||||
'item-3': { id: 'item-3', content: 'Item 3' },
|
||||
'item-4': { id: 'item-4', content: 'Item 4' },
|
||||
'item-5': { id: 'item-5', content: 'Item 5' },
|
||||
'item-6': { id: 'item-6', content: 'Item 6' },
|
||||
};
|
||||
for (let i = 7; i <= 20; i++) {
|
||||
const key = `item-${i}`;
|
||||
items[key] = { id: key, content: `Item ${i}` };
|
||||
}
|
||||
|
||||
export const initialBoard = [
|
||||
{
|
||||
id: 'column-1',
|
||||
title: 'New',
|
||||
colorCode: '#B76796',
|
||||
itemKeys: [
|
||||
'item-1',
|
||||
'item-2',
|
||||
'item-3',
|
||||
'item-4',
|
||||
'item-7',
|
||||
'item-8',
|
||||
'item-9',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'column-2',
|
||||
title: 'Screening',
|
||||
colorCode: '#CB912F',
|
||||
itemKeys: ['item-5', 'item-6'],
|
||||
},
|
||||
{
|
||||
id: 'column-3',
|
||||
colorCode: '#9065B0',
|
||||
title: 'Meeting',
|
||||
itemKeys: [],
|
||||
},
|
||||
{
|
||||
id: 'column-4',
|
||||
title: 'Proposal',
|
||||
colorCode: '#337EA9',
|
||||
itemKeys: [],
|
||||
},
|
||||
{
|
||||
id: 'column-5',
|
||||
colorCode: '#079039',
|
||||
title: 'Customer',
|
||||
itemKeys: [],
|
||||
},
|
||||
] satisfies Column[];
|
||||
Reference in New Issue
Block a user