Improve Supply event chart style
This commit is contained in:
@@ -6,10 +6,9 @@ import {
|
|||||||
differenceInCalendarDays,
|
differenceInCalendarDays,
|
||||||
differenceInCalendarWeeks,
|
differenceInCalendarWeeks,
|
||||||
format,
|
format,
|
||||||
subDays,
|
|
||||||
} from 'date-fns'
|
} from 'date-fns'
|
||||||
import { times } from 'ramda'
|
import { times } from 'ramda'
|
||||||
import { useMemo, MouseEventHandler } from 'react'
|
import React, { useMemo, MouseEventHandler } from 'react'
|
||||||
|
|
||||||
export interface GanttChartItem {
|
export interface GanttChartItem {
|
||||||
id: string
|
id: string
|
||||||
@@ -26,6 +25,11 @@ interface GanttChartProps {
|
|||||||
items: GanttChartItem[]
|
items: GanttChartItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const widthOfDay = 20
|
||||||
|
const widthOfWeek = widthOfDay * 7
|
||||||
|
|
||||||
|
const itemHeight = 30
|
||||||
|
|
||||||
const GanttChart = ({
|
const GanttChart = ({
|
||||||
startDate: startDateString,
|
startDate: startDateString,
|
||||||
endDate: endDateString,
|
endDate: endDateString,
|
||||||
@@ -34,8 +38,8 @@ const GanttChart = ({
|
|||||||
}: GanttChartProps) => {
|
}: GanttChartProps) => {
|
||||||
const startDate = new Date(startDateString)
|
const startDate = new Date(startDateString)
|
||||||
const endDate = new Date(endDateString)
|
const endDate = new Date(endDateString)
|
||||||
const firstDateToRender = subDays(startDate, startDate.getDay() - 1)
|
const firstDateToRender = startDate
|
||||||
const lastDateToRender = addDays(endDate, 6 - endDate.getDay() + 1)
|
const lastDateToRender = endDate
|
||||||
const todayDate = new Date(todayDateString)
|
const todayDate = new Date(todayDateString)
|
||||||
|
|
||||||
const daysToRender = differenceInCalendarDays(
|
const daysToRender = differenceInCalendarDays(
|
||||||
@@ -53,92 +57,56 @@ const GanttChart = ({
|
|||||||
}, 1)
|
}, 1)
|
||||||
}, [items])
|
}, [items])
|
||||||
|
|
||||||
return (
|
|
||||||
<Box sx={{ width: weeksToRender * 280 + 70 }}>
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
marginLeft: -20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{times((index) => {
|
|
||||||
const weekNumber = index + 1
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
key={`week-${weekNumber}`}
|
sx={{ width: weeksToRender * widthOfWeek + 70, marginLeft: widthOfDay }}
|
||||||
sx={{
|
|
||||||
width: 280,
|
|
||||||
textAlign: 'center',
|
|
||||||
fontWeight: 700,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Week {weekNumber}
|
<WeekLabelRow
|
||||||
</Box>
|
firstDateToRender={firstDateToRender}
|
||||||
)
|
weeksToRender={weeksToRender}
|
||||||
}, weeksToRender)}
|
/>
|
||||||
</Flex>
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
height: totalRow * 50 + 40,
|
height: totalRow * (itemHeight + 10) + 30,
|
||||||
borderBottomStyle: 'solid',
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
borderBottomColor: 'border',
|
|
||||||
borderTopStyle: 'solid',
|
|
||||||
borderTopWidth: 1,
|
|
||||||
borderTopColor: 'border',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{times((index) => {
|
{times((index) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<DateMeasure
|
||||||
key={`day-border-${index}`}
|
key={`day-border-${index}`}
|
||||||
sx={{
|
index={index}
|
||||||
position: 'absolute',
|
totalRow={totalRow}
|
||||||
height: totalRow * 50 + 40,
|
|
||||||
borderRightStyle: 'solid',
|
|
||||||
borderRightWidth: 1,
|
|
||||||
borderRightColor: index % 7 === 6 ? 'border' : 'altBorder',
|
|
||||||
left: (index + 1) * 40 - 1 - 20,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}, daysToRender + 1)}
|
}, daysToRender)}
|
||||||
|
|
||||||
{times((index) => {
|
{times((index) => {
|
||||||
const weekNumber = index + 1
|
|
||||||
return (
|
return (
|
||||||
<Text
|
<Box
|
||||||
key={`week-start-date-${index}`}
|
key={`weekdate-${index}`}
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
color: 'border',
|
left: (index - 1) * widthOfDay,
|
||||||
zIndex: 21,
|
width: widthOfDay,
|
||||||
top: 0,
|
textAlign: 'center',
|
||||||
left: weekNumber * 280 - 15,
|
color:
|
||||||
width: 300,
|
index - (1 % 7) === 3
|
||||||
pointerEvents: 'none',
|
? 'red'
|
||||||
|
: index - (1 % 7) === 2
|
||||||
|
? 'blue'
|
||||||
|
: 'default',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{format(addWeeks(firstDateToRender, weekNumber), 'PP')}
|
{format(addDays(firstDateToRender, index - 1), 'EEEEE')}
|
||||||
</Text>
|
</Box>
|
||||||
)
|
)
|
||||||
}, weeksToRender - 1)}
|
}, daysToRender + 2)}
|
||||||
<Box
|
|
||||||
sx={{
|
<TodayBox
|
||||||
boxSizing: 'border-box',
|
totalRow={totalRow}
|
||||||
position: 'absolute',
|
todayDate={todayDate}
|
||||||
width: 40,
|
firstDateToRender={firstDateToRender}
|
||||||
height: totalRow * 50 + 40,
|
|
||||||
backgroundColor: 'blue.5',
|
|
||||||
borderStyle: 'solid',
|
|
||||||
borderColor: 'blue.7',
|
|
||||||
opacity: 0.2,
|
|
||||||
zIndex: 20,
|
|
||||||
borderRadius: 4,
|
|
||||||
left:
|
|
||||||
differenceInCalendarDays(todayDate, firstDateToRender) * 40 - 20,
|
|
||||||
pointerEvents: 'none',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
@@ -146,22 +114,11 @@ const GanttChart = ({
|
|||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
width: 1,
|
width: 1,
|
||||||
height: totalRow * 50 + 40,
|
height: totalRow * (itemHeight + 10) + itemHeight,
|
||||||
backgroundColor: 'red.3',
|
backgroundColor: 'red.3',
|
||||||
zIndex: 20,
|
zIndex: 20,
|
||||||
left: differenceInCalendarDays(startDate, firstDateToRender) * 40,
|
left:
|
||||||
pointerEvents: 'none',
|
differenceInCalendarDays(endDate, firstDateToRender) * widthOfDay,
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
position: 'absolute',
|
|
||||||
width: 1,
|
|
||||||
height: totalRow * 50 + 40,
|
|
||||||
backgroundColor: 'red.3',
|
|
||||||
zIndex: 20,
|
|
||||||
left: differenceInCalendarDays(endDate, firstDateToRender) * 40,
|
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -171,25 +128,11 @@ const GanttChart = ({
|
|||||||
transform: 'rotate(90deg)',
|
transform: 'rotate(90deg)',
|
||||||
color: 'red.5',
|
color: 'red.5',
|
||||||
zIndex: 21,
|
zIndex: 21,
|
||||||
top: 150,
|
top: 170,
|
||||||
left:
|
left:
|
||||||
differenceInCalendarDays(startDate, firstDateToRender) * 40 +
|
differenceInCalendarDays(endDate, firstDateToRender) *
|
||||||
-160,
|
widthOfDay +
|
||||||
width: 300,
|
-140,
|
||||||
pointerEvents: 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{format(startDate, 'PP')}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
transform: 'rotate(90deg)',
|
|
||||||
color: 'red.5',
|
|
||||||
zIndex: 21,
|
|
||||||
top: 150,
|
|
||||||
left:
|
|
||||||
differenceInCalendarDays(endDate, firstDateToRender) * 40 + -140,
|
|
||||||
width: 300,
|
width: 300,
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
}}
|
}}
|
||||||
@@ -197,41 +140,25 @@ const GanttChart = ({
|
|||||||
{format(endDate, 'PP')}
|
{format(endDate, 'PP')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
color: 'blue.7',
|
|
||||||
transform: 'rotate(90deg)',
|
|
||||||
zIndex: 21,
|
|
||||||
top: 150,
|
|
||||||
left:
|
|
||||||
differenceInCalendarDays(new Date(todayDate), firstDateToRender) *
|
|
||||||
40 -
|
|
||||||
150,
|
|
||||||
width: 300,
|
|
||||||
pointerEvents: 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Today ({format(todayDate, 'PP')})
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const offset =
|
const offset =
|
||||||
differenceInCalendarDays(
|
differenceInCalendarDays(
|
||||||
new Date(item.duration[0]),
|
new Date(item.duration[0]),
|
||||||
firstDateToRender
|
firstDateToRender
|
||||||
) * 40
|
) *
|
||||||
|
widthOfDay -
|
||||||
|
widthOfDay / 2
|
||||||
const length =
|
const length =
|
||||||
differenceInCalendarDays(
|
differenceInCalendarDays(
|
||||||
new Date(item.duration[1]),
|
new Date(item.duration[1]),
|
||||||
new Date(item.duration[0])
|
new Date(item.duration[0])
|
||||||
) * 40
|
) * widthOfDay
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
key={item.id}
|
key={item.id}
|
||||||
py={2}
|
py={2}
|
||||||
px={3}
|
px={2}
|
||||||
sx={{
|
sx={{
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -241,13 +168,13 @@ const GanttChart = ({
|
|||||||
backgroundColor: 'background',
|
backgroundColor: 'background',
|
||||||
width: length,
|
width: length,
|
||||||
left: offset,
|
left: offset,
|
||||||
top: (item.row - 1) * 50 + 20,
|
top: (item.row - 1) * (itemHeight + 10) + 30,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
height: 40,
|
height: itemHeight,
|
||||||
borderRadius: 40,
|
borderRadius: itemHeight / 2,
|
||||||
fontWeight: 700,
|
fontSize: 1,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
minWidth: length,
|
minWidth: length,
|
||||||
@@ -268,3 +195,103 @@ const GanttChart = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default GanttChart
|
export default GanttChart
|
||||||
|
|
||||||
|
const WeekLabelRow = ({
|
||||||
|
weeksToRender,
|
||||||
|
firstDateToRender,
|
||||||
|
}: {
|
||||||
|
weeksToRender: number
|
||||||
|
firstDateToRender: Date
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Flex sx={{}}>
|
||||||
|
{times((index) => {
|
||||||
|
const weekNumber = index
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
key={`week-${weekNumber}`}
|
||||||
|
sx={{
|
||||||
|
width: widthOfWeek,
|
||||||
|
color: 'textMuted',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{format(addWeeks(firstDateToRender, weekNumber), 'PP')}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}, weeksToRender)}
|
||||||
|
</Flex>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const DateMeasure = ({
|
||||||
|
index,
|
||||||
|
totalRow,
|
||||||
|
}: {
|
||||||
|
index: number
|
||||||
|
totalRow: number
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
key={`day-border-${index}`}
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
height: totalRow * 50 + widthOfDay,
|
||||||
|
borderRightStyle: index % 7 === 0 ? 'solid' : 'dashed',
|
||||||
|
borderRightWidth: 1,
|
||||||
|
borderRightColor: index % 7 === 0 ? 'border' : 'altBorder',
|
||||||
|
left: index * widthOfDay,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const TodayBox = ({
|
||||||
|
totalRow,
|
||||||
|
todayDate,
|
||||||
|
firstDateToRender,
|
||||||
|
}: {
|
||||||
|
totalRow: number
|
||||||
|
todayDate: Date
|
||||||
|
firstDateToRender: Date
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
color: 'blue.7',
|
||||||
|
transform: 'rotate(90deg)',
|
||||||
|
zIndex: 21,
|
||||||
|
top: 170,
|
||||||
|
left:
|
||||||
|
differenceInCalendarDays(new Date(todayDate), firstDateToRender) *
|
||||||
|
widthOfDay -
|
||||||
|
160,
|
||||||
|
width: 300,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Today ({format(todayDate, 'PP')})
|
||||||
|
</Text>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
position: 'absolute',
|
||||||
|
width: widthOfDay,
|
||||||
|
height: totalRow * (itemHeight + 10) + itemHeight,
|
||||||
|
backgroundColor: 'blue.5',
|
||||||
|
borderStyle: 'solid',
|
||||||
|
borderColor: 'blue.7',
|
||||||
|
borderRadius: 4,
|
||||||
|
opacity: 0.3,
|
||||||
|
zIndex: 20,
|
||||||
|
left:
|
||||||
|
differenceInCalendarDays(todayDate, firstDateToRender) *
|
||||||
|
widthOfDay -
|
||||||
|
20,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user