Skip to content

Commit 3802be9

Browse files
authored
feat: combine cards in lines to be compact (#17)
1 parent 69eab01 commit 3802be9

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

src/components/ProjectTimeline.tsx

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useRef, useEffect, ReactNode } from 'react';
1+
import React, { useState, useRef, useEffect, ReactNode, useMemo } from 'react';
22
import moment from 'moment';
33
import {
44
Box,
@@ -14,6 +14,7 @@ import {
1414
SystemProps,
1515
useColorModeValue,
1616
} from '@chakra-ui/react';
17+
import { orderBy } from 'lodash';
1718
import { useErrorToast } from '@/lib/customToast';
1819

1920
interface 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+
5581
const 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

Comments
 (0)