Sammy/t 392 aau i can drag and drop opportunities (#257)
* refactor: extract data from Board component * feature: display board on opportunities page * test: add strict mode in storybook * chore: replace dnd to make it work with React 18 and strict mode Atlassion has not fixed this issue in a year so we use the fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350 * refactor: move mocked-data in a file * chore: use real column names in mock data * feature: design columns * feature: add New button at bottum of columns * bugfix: move header out of dragable so the cards does not flicker on drop * lint: remove useless imports * refactor: rename board item key
This commit is contained in:
120
front/package-lock.json
generated
120
front/package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@apollo/client": "^3.7.5",
|
"@apollo/client": "^3.7.5",
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.10.6",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.5",
|
||||||
|
"@hello-pangea/dnd": "^16.2.0",
|
||||||
"@tabler/icons-react": "^2.20.0",
|
"@tabler/icons-react": "^2.20.0",
|
||||||
"@tanstack/react-table": "^8.8.5",
|
"@tanstack/react-table": "^8.8.5",
|
||||||
"@types/node": "^16.18.4",
|
"@types/node": "^16.18.4",
|
||||||
@ -23,7 +24,6 @@
|
|||||||
"libphonenumber-js": "^1.10.26",
|
"libphonenumber-js": "^1.10.26",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
|
||||||
"react-datepicker": "^4.11.0",
|
"react-datepicker": "^4.11.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hotkeys-hook": "^4.4.0",
|
"react-hotkeys-hook": "^4.4.0",
|
||||||
@ -59,7 +59,6 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/jest": "^27.5.2",
|
"@types/jest": "^27.5.2",
|
||||||
"@types/luxon": "^3.3.0",
|
"@types/luxon": "^3.3.0",
|
||||||
"@types/react-beautiful-dnd": "^13.1.4",
|
|
||||||
"@types/react-datepicker": "^4.11.2",
|
"@types/react-datepicker": "^4.11.2",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
@ -4470,6 +4469,24 @@
|
|||||||
"@hapi/hoek": "^9.0.0"
|
"@hapi/hoek": "^9.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@hello-pangea/dnd": {
|
||||||
|
"version": "16.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hello-pangea/dnd/-/dnd-16.2.0.tgz",
|
||||||
|
"integrity": "sha512-inACvMcvvLr34CG0P6+G/3bprVKhwswxjcsFUSJ+fpOGjhvDj9caiA9X3clby0lgJ6/ILIJjyedHZYECB7GAgA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.19.4",
|
||||||
|
"css-box-model": "^1.2.1",
|
||||||
|
"memoize-one": "^6.0.0",
|
||||||
|
"raf-schd": "^4.0.3",
|
||||||
|
"react-redux": "^8.0.4",
|
||||||
|
"redux": "^4.2.0",
|
||||||
|
"use-memo-one": "^1.1.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.8",
|
"version": "0.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||||
@ -11185,15 +11202,6 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-beautiful-dnd": {
|
|
||||||
"version": "13.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.4.tgz",
|
|
||||||
"integrity": "sha512-4bIBdzOr0aavN+88q3C7Pgz+xkb7tz3whORYrmSj77wfVEMfiWiooIwVWFR7KM2e+uGTe5BVrXqSfb0aHeflJA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/react": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/react-datepicker": {
|
"node_modules/@types/react-datepicker": {
|
||||||
"version": "4.11.2",
|
"version": "4.11.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz",
|
||||||
@ -11214,17 +11222,6 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/react-redux": {
|
|
||||||
"version": "7.1.25",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz",
|
|
||||||
"integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/hoist-non-react-statics": "^3.3.0",
|
|
||||||
"@types/react": "*",
|
|
||||||
"hoist-non-react-statics": "^3.3.0",
|
|
||||||
"redux": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||||
@ -11340,6 +11337,11 @@
|
|||||||
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==",
|
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/use-sync-external-store": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
|
||||||
|
},
|
||||||
"node_modules/@types/uuid": {
|
"node_modules/@types/uuid": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz",
|
||||||
@ -28473,9 +28475,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/memoize-one": {
|
"node_modules/memoize-one": {
|
||||||
"version": "5.2.1",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
|
||||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
|
||||||
},
|
},
|
||||||
"node_modules/memoizerific": {
|
"node_modules/memoizerific": {
|
||||||
"version": "1.11.3",
|
"version": "1.11.3",
|
||||||
@ -32214,24 +32216,6 @@
|
|||||||
"asap": "~2.0.6"
|
"asap": "~2.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-beautiful-dnd": {
|
|
||||||
"version": "13.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz",
|
|
||||||
"integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.9.2",
|
|
||||||
"css-box-model": "^1.2.0",
|
|
||||||
"memoize-one": "^5.1.1",
|
|
||||||
"raf-schd": "^4.0.2",
|
|
||||||
"react-redux": "^7.2.0",
|
|
||||||
"redux": "^4.0.4",
|
|
||||||
"use-memo-one": "^1.1.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8.5 || ^17.0.0 || ^18.0.0",
|
|
||||||
"react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-colorful": {
|
"node_modules/react-colorful": {
|
||||||
"version": "5.6.1",
|
"version": "5.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
|
||||||
@ -32627,33 +32611,51 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-redux": {
|
"node_modules/react-redux": {
|
||||||
"version": "7.2.9",
|
"version": "8.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.7.tgz",
|
||||||
"integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==",
|
"integrity": "sha512-1vRQuCQI5Y2uNmrMXg81RXKiBHY3jBzvCvNmZF437O/Z9/pZ+ba2uYHbemYXb3g8rjsacBGo+/wmfrQKzMhJsg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.15.4",
|
"@babel/runtime": "^7.12.1",
|
||||||
"@types/react-redux": "^7.1.20",
|
"@types/hoist-non-react-statics": "^3.3.1",
|
||||||
|
"@types/use-sync-external-store": "^0.0.3",
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
"loose-envify": "^1.4.0",
|
"react-is": "^18.0.0",
|
||||||
"prop-types": "^15.7.2",
|
"use-sync-external-store": "^1.0.0"
|
||||||
"react-is": "^17.0.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8.3 || ^17 || ^18"
|
"@reduxjs/toolkit": "^1 || ^2.0.0-beta.0",
|
||||||
|
"@types/react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0",
|
||||||
|
"react-native": ">=0.59",
|
||||||
|
"redux": "^4 || ^5.0.0-beta.0"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
|
"@reduxjs/toolkit": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"react-native": {
|
"react-native": {
|
||||||
"optional": true
|
"optional": true
|
||||||
|
},
|
||||||
|
"redux": {
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-redux/node_modules/react-is": {
|
"node_modules/react-redux/node_modules/react-is": {
|
||||||
"version": "17.0.2",
|
"version": "18.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
|
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||||
},
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
@ -37690,6 +37692,14 @@
|
|||||||
"react-dom": "16.8.0 - 18"
|
"react-dom": "16.8.0 - 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-sync-external-store": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util": {
|
"node_modules/util": {
|
||||||
"version": "0.12.5",
|
"version": "0.12.5",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
"@apollo/client": "^3.7.5",
|
"@apollo/client": "^3.7.5",
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.10.6",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.5",
|
||||||
|
"@hello-pangea/dnd": "^16.2.0",
|
||||||
"@tabler/icons-react": "^2.20.0",
|
"@tabler/icons-react": "^2.20.0",
|
||||||
"@tanstack/react-table": "^8.8.5",
|
"@tanstack/react-table": "^8.8.5",
|
||||||
"@types/node": "^16.18.4",
|
"@types/node": "^16.18.4",
|
||||||
@ -18,7 +19,6 @@
|
|||||||
"libphonenumber-js": "^1.10.26",
|
"libphonenumber-js": "^1.10.26",
|
||||||
"luxon": "^3.3.0",
|
"luxon": "^3.3.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
|
||||||
"react-datepicker": "^4.11.0",
|
"react-datepicker": "^4.11.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hotkeys-hook": "^4.4.0",
|
"react-hotkeys-hook": "^4.4.0",
|
||||||
@ -103,7 +103,6 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/jest": "^27.5.2",
|
"@types/jest": "^27.5.2",
|
||||||
"@types/luxon": "^3.3.0",
|
"@types/luxon": "^3.3.0",
|
||||||
"@types/react-beautiful-dnd": "^13.1.4",
|
|
||||||
"@types/react-datepicker": "^4.11.2",
|
"@types/react-datepicker": "^4.11.2",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import {
|
import {
|
||||||
DragDropContext,
|
DragDropContext,
|
||||||
Draggable,
|
Draggable,
|
||||||
Droppable,
|
Droppable,
|
||||||
OnDragEndResponder,
|
OnDragEndResponder,
|
||||||
} from 'react-beautiful-dnd';
|
} from '@hello-pangea/dnd';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
|
// 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 { BoardCard } from './BoardCard';
|
import { BoardCard } from './BoardCard';
|
||||||
import { BoardColumn } from './BoardColumn';
|
import { BoardColumn } from './BoardColumn';
|
||||||
|
|
||||||
@ -16,43 +18,27 @@ const StyledBoard = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type ItemKey = `item-${number}`;
|
export type BoardItemKey = `item-${number}`;
|
||||||
interface Item {
|
export interface Item {
|
||||||
id: string;
|
id: string;
|
||||||
content: string;
|
content: string;
|
||||||
}
|
}
|
||||||
interface Items {
|
export interface Items {
|
||||||
[key: string]: Item;
|
[key: string]: Item;
|
||||||
}
|
}
|
||||||
interface Column {
|
export interface Column {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
itemKeys: ItemKey[];
|
colorCode?: string;
|
||||||
|
itemKeys: BoardItemKey[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const items: Items = {
|
type BoardProps = {
|
||||||
'item-1': { id: 'item-1', content: 'Item 1' },
|
initialBoard: Column[];
|
||||||
'item-2': { id: 'item-2', content: 'Item 2' },
|
items: Items;
|
||||||
'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' },
|
|
||||||
} satisfies Record<ItemKey, { id: ItemKey; content: string }>;
|
|
||||||
|
|
||||||
const initialBoard = [
|
export const Board = ({ initialBoard, items }: BoardProps) => {
|
||||||
{
|
|
||||||
id: 'column-1',
|
|
||||||
title: 'Column 1',
|
|
||||||
itemKeys: ['item-1', 'item-2', 'item-3', 'item-4'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'column-2',
|
|
||||||
title: 'Column 2',
|
|
||||||
itemKeys: ['item-5', 'item-6'],
|
|
||||||
},
|
|
||||||
] satisfies Column[];
|
|
||||||
|
|
||||||
export const Board = () => {
|
|
||||||
const [board, setBoard] = useState<Column[]>(initialBoard);
|
const [board, setBoard] = useState<Column[]>(initialBoard);
|
||||||
|
|
||||||
const onDragEnd: OnDragEndResponder = useCallback(
|
const onDragEnd: OnDragEndResponder = useCallback(
|
||||||
@ -99,7 +85,11 @@ export const Board = () => {
|
|||||||
<Droppable key={column.id} droppableId={column.id}>
|
<Droppable key={column.id} droppableId={column.id}>
|
||||||
{(provided) =>
|
{(provided) =>
|
||||||
provided && (
|
provided && (
|
||||||
<BoardColumn title={column.title} droppableProvided={provided}>
|
<BoardColumn
|
||||||
|
title={column.title}
|
||||||
|
colorCode={column.colorCode}
|
||||||
|
droppableProvided={provided}
|
||||||
|
>
|
||||||
{column.itemKeys.map((itemKey, index) => (
|
{column.itemKeys.map((itemKey, index) => (
|
||||||
<Draggable
|
<Draggable
|
||||||
key={itemKey}
|
key={itemKey}
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { DraggableProvided } from 'react-beautiful-dnd';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { DraggableProvided } from '@hello-pangea/dnd';
|
||||||
|
|
||||||
const StyledCard = styled.div`
|
const StyledCard = styled.div`
|
||||||
background-color: #ffffff;
|
background-color: ${({ theme }) => theme.secondaryBackground};
|
||||||
|
border: 1px solid ${({ theme }) => theme.quaternaryBackground};
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 16px;
|
padding: 8px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 8px;
|
||||||
|
box-shadow: ${({ theme }) => theme.boxShadow};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type BoardCardProps = {
|
type BoardCardProps = {
|
||||||
|
|||||||
@ -1,35 +1,53 @@
|
|||||||
import { DroppableProvided } from 'react-beautiful-dnd';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { DroppableProvided } from '@hello-pangea/dnd';
|
||||||
|
|
||||||
|
import { NewButton } from './BoardNewButton';
|
||||||
|
|
||||||
const StyledColumn = styled.div`
|
const StyledColumn = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
margin-right: 16px;
|
background-color: ${({ theme }) => theme.primaryBackground};
|
||||||
background-color: #f5f5f5;
|
padding: ${({ theme }) => theme.spacing(2)};
|
||||||
border-radius: 4px;
|
|
||||||
padding: 16px;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledColumnTitle = styled.h3`
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: ${({ theme }) => theme.fontWeightBold};
|
||||||
|
font-size: ${({ theme }) => theme.fontSizeMedium};
|
||||||
|
line-height: ${({ theme }) => theme.lineHeight};
|
||||||
|
color: ${({ color }) => color};
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ItemContainer = styled.div``;
|
||||||
|
|
||||||
type BoardColumnProps = {
|
type BoardColumnProps = {
|
||||||
title: string;
|
title: string;
|
||||||
|
colorCode?: string;
|
||||||
children: any[];
|
children: any[];
|
||||||
droppableProvided: DroppableProvided;
|
droppableProvided: DroppableProvided;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BoardColumn = ({
|
export const BoardColumn = ({
|
||||||
title,
|
title,
|
||||||
|
colorCode,
|
||||||
children,
|
children,
|
||||||
droppableProvided,
|
droppableProvided,
|
||||||
}: BoardColumnProps) => {
|
}: BoardColumnProps) => {
|
||||||
return (
|
return (
|
||||||
<StyledColumn
|
<StyledColumn>
|
||||||
ref={droppableProvided.innerRef}
|
<StyledColumnTitle color={colorCode}>• {title}</StyledColumnTitle>
|
||||||
{...droppableProvided.droppableProps}
|
<ItemContainer
|
||||||
>
|
ref={droppableProvided.innerRef}
|
||||||
<h3>{title}</h3>
|
{...droppableProvided.droppableProps}
|
||||||
{children}
|
>
|
||||||
{droppableProvided.placeholder}
|
{children}
|
||||||
|
{droppableProvided.placeholder}
|
||||||
|
<NewButton />
|
||||||
|
</ItemContainer>
|
||||||
</StyledColumn>
|
</StyledColumn>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
29
front/src/modules/ui/components/board/BoardNewButton.tsx
Normal file
29
front/src/modules/ui/components/board/BoardNewButton.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { IconPlus } from '@tabler/icons-react';
|
||||||
|
|
||||||
|
const StyledButton = styled.button`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: ${({ theme }) => theme.primaryBackground};
|
||||||
|
color: ${({ theme }) => theme.text40};
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s ease-in-out;
|
||||||
|
align-self: baseline;
|
||||||
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: ${({ theme }) => theme.secondaryBackground};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const NewButton = () => {
|
||||||
|
return (
|
||||||
|
<StyledButton>
|
||||||
|
<IconPlus size={16} />
|
||||||
|
New
|
||||||
|
</StyledButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,7 +1,10 @@
|
|||||||
|
import { StrictMode } from 'react';
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
import { Board } from '../Board';
|
import { Board } from '../Board';
|
||||||
|
|
||||||
|
import { initialBoard, items } from './mock-data';
|
||||||
|
|
||||||
const meta: Meta<typeof Board> = {
|
const meta: Meta<typeof Board> = {
|
||||||
title: 'Components/Board',
|
title: 'Components/Board',
|
||||||
component: Board,
|
component: Board,
|
||||||
@ -11,5 +14,9 @@ export default meta;
|
|||||||
type Story = StoryObj<typeof Board>;
|
type Story = StoryObj<typeof Board>;
|
||||||
|
|
||||||
export const OneColumnBoard: Story = {
|
export const OneColumnBoard: Story = {
|
||||||
render: () => <Board />,
|
render: () => (
|
||||||
|
<StrictMode>
|
||||||
|
<Board initialBoard={initialBoard} items={items} />
|
||||||
|
</StrictMode>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,55 @@
|
|||||||
|
import { Column, Items } from '../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[];
|
||||||
@ -67,6 +67,8 @@ const lightThemeSpecific = {
|
|||||||
|
|
||||||
blueHighTransparency: 'rgba(25, 97, 237, 0.03)',
|
blueHighTransparency: 'rgba(25, 97, 237, 0.03)',
|
||||||
blueLowTransparency: 'rgba(25, 97, 237, 0.32)',
|
blueLowTransparency: 'rgba(25, 97, 237, 0.32)',
|
||||||
|
|
||||||
|
boxShadow: '0px 2px 4px 0px #0F0F0F0A',
|
||||||
};
|
};
|
||||||
|
|
||||||
const darkThemeSpecific: typeof lightThemeSpecific = {
|
const darkThemeSpecific: typeof lightThemeSpecific = {
|
||||||
@ -107,6 +109,7 @@ const darkThemeSpecific: typeof lightThemeSpecific = {
|
|||||||
|
|
||||||
blueHighTransparency: 'rgba(104, 149, 236, 0.03)',
|
blueHighTransparency: 'rgba(104, 149, 236, 0.03)',
|
||||||
blueLowTransparency: 'rgba(104, 149, 236, 0.32)',
|
blueLowTransparency: 'rgba(104, 149, 236, 0.32)',
|
||||||
|
boxShadow: '0px 2px 4px 0px #0F0F0F0A', // TODO change color for dark theme
|
||||||
};
|
};
|
||||||
|
|
||||||
export const overlayBackground = (props: any) =>
|
export const overlayBackground = (props: any) =>
|
||||||
|
|||||||
@ -2,10 +2,16 @@ import { FaBullseye } from 'react-icons/fa';
|
|||||||
|
|
||||||
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
import { WithTopBarContainer } from '@/ui/layout/containers/WithTopBarContainer';
|
||||||
|
|
||||||
|
import {
|
||||||
|
initialBoard,
|
||||||
|
items,
|
||||||
|
} from '../../modules/ui/components/board/__stories__/mock-data';
|
||||||
|
import { Board } from '../../modules/ui/components/board/Board';
|
||||||
|
|
||||||
export function Opportunities() {
|
export function Opportunities() {
|
||||||
return (
|
return (
|
||||||
<WithTopBarContainer title="Opportunities" icon={<FaBullseye />}>
|
<WithTopBarContainer title="Opportunities" icon={<FaBullseye />}>
|
||||||
<></>
|
<Board initialBoard={initialBoard} items={items} />
|
||||||
</WithTopBarContainer>
|
</WithTopBarContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user