1- import React , { useState , useRef , useEffect , ReactNode } from 'react' ;
1+ import React , { useState , useRef , useEffect , ReactNode , useMemo } from 'react' ;
22import moment from 'moment' ;
33import {
44 Box ,
@@ -14,6 +14,7 @@ import {
1414 SystemProps ,
1515 useColorModeValue ,
1616} from '@chakra-ui/react' ;
17+ import { orderBy } from 'lodash' ;
1718import { useErrorToast } from '@/lib/customToast' ;
1819
1920interface OwnerItem {
@@ -52,12 +53,37 @@ while (startDateMoment.isBefore(endDateMoment)) {
5253 startDateMoment . add ( 1 , 'day' ) ;
5354}
5455
56+ /** card1.startDate < card2.startDate */
57+ const canPlaceToOneLine = ( card1 : CardInfo , card2 : CardInfo , gapDays : number ) => {
58+ return moment ( card1 . endDate ) . add ( gapDays , 'days' ) . isBefore ( card2 . startDate ) ;
59+ } ;
60+ const getCompactTimelines = ( cards : CardInfo [ ] ) => {
61+ const sortedCards = orderBy ( cards , 'startDate' ) ;
62+ const lines : CardInfo [ ] [ ] = [ ] ;
63+
64+ for ( const card of sortedCards ) {
65+ let placed = false ;
66+ for ( const line of lines ) {
67+ if ( canPlaceToOneLine ( line . at ( - 1 ) ! , card , 2 ) ) {
68+ line . push ( card ) ;
69+ placed = true ;
70+ break ;
71+ }
72+ }
73+
74+ if ( placed ) continue ;
75+ lines . push ( [ card ] ) ;
76+ }
77+
78+ return lines . reverse ( ) ;
79+ } ;
80+
5581const Timeline = ( props : SystemProps ) => {
5682 const toastError = useErrorToast ( ) ;
5783 const todayRef = useRef < HTMLDivElement | null > ( null ) ;
5884 const scrollContainerRef = useRef < HTMLDivElement | null > ( null ) ;
5985
60- const [ cards , setCards ] = useState ( [ ] ) ;
86+ const [ cards , setCards ] = useState < CardInfo [ ] > ( [ ] ) ;
6187 const [ displayDates , setDisplayDates ] = useState < string [ ] > ( [ ] ) ;
6288
6389 const gridBgColor = useColorModeValue ( '#FFF' , 'gray.800' ) ;
@@ -106,6 +132,10 @@ const Timeline = (props: SystemProps) => {
106132 ) ;
107133 } ;
108134
135+ const renderTimeline = ( cards : CardInfo [ ] , index : number ) => {
136+ return cards . map ( ( card ) => renderCardGrid ( card , index ) ) ;
137+ }
138+
109139 const renderCard = ( card : CardInfo ) => {
110140 return (
111141 < Flex
@@ -257,6 +287,8 @@ const Timeline = (props: SystemProps) => {
257287 } ) ;
258288 } ;
259289
290+ const lines = useMemo ( ( ) => getCompactTimelines ( cards ) , [ cards ] ) ;
291+
260292 return (
261293 < Box
262294 minH = "200px"
@@ -302,7 +334,7 @@ const Timeline = (props: SystemProps) => {
302334 templateColumns = { `repeat(${ displayDates . length } , 1fr)` }
303335 >
304336 { renderWeekendGrids ( displayDates ) }
305- { cards . map ( ( cardInfo , index ) => renderCardGrid ( cardInfo , index ) ) }
337+ { lines . map ( ( cards , index ) => renderTimeline ( cards , index ) ) }
306338 </ Grid >
307339 ) : (
308340 < Skeleton w = "100%" h = "100%" > </ Skeleton >
0 commit comments