Skip to content

Commit 7853712

Browse files
committed
feat: compute and pass global max availability across day planners
- Added logic to calculate global maximum availability based on user timeblocks. - Updated DayPlanner, DayPlanners, DayTime, and PreviewDayTime components to accept and utilize the globalMaxAvailable prop. - Enhanced best times functionality to leverage the computed global max availability for improved user experience.
1 parent e9f8778 commit 7853712

File tree

4 files changed

+51
-34
lines changed

4 files changed

+51
-34
lines changed

apps/web/src/app/[locale]/(marketing)/meet-together/plans/[planId]/day-planner.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default function DayPlanner({
1212
editable,
1313
disabled,
1414
showBestTimes = false,
15+
globalMaxAvailable,
1516
onBestTimesStatus,
1617
}: {
1718
timeblocks: Timeblock[];
@@ -21,6 +22,7 @@ export default function DayPlanner({
2122
editable: boolean;
2223
disabled: boolean;
2324
showBestTimes?: boolean;
25+
globalMaxAvailable: number;
2426
onBestTimesStatus?: (hasBestTimes: boolean) => void;
2527
}) {
2628
const locale = useLocale();
@@ -47,6 +49,7 @@ export default function DayPlanner({
4749
editable={editable}
4850
disabled={disabled}
4951
showBestTimes={showBestTimes}
52+
globalMaxAvailable={globalMaxAvailable}
5053
onBestTimesStatus={onBestTimesStatus}
5154
/>
5255
</div>

apps/web/src/app/[locale]/(marketing)/meet-together/plans/[planId]/day-planners.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import DayPlanner from './day-planner';
22
import { useTimeBlocking } from './time-blocking-provider';
33
import type { Timeblock } from '@tuturuuu/types/primitives/Timeblock';
4+
import dayjs from 'dayjs';
45
import { useCallback, useEffect, useState } from 'react';
56

67
export default function DayPlanners({
@@ -69,6 +70,35 @@ export default function DayPlanners({
6970
};
7071
}, [editing.enabled]);
7172

73+
// Compute global max availability across all days
74+
const hourSplits = 4;
75+
let globalMaxAvailable = 0;
76+
dates.forEach((d) => {
77+
const dayTimeblocks = timeblocks.filter((tb) => tb.date === d);
78+
const hourBlocks = Array.from(Array(Math.floor(end + 1 - start)).keys());
79+
const slotAvailableCounts: number[] = hourBlocks
80+
.map((i) => (i + start) * hourSplits)
81+
.flatMap((i) => Array(hourSplits).fill(i))
82+
.map((_, i) => {
83+
const currentDate = dayjs(d)
84+
.hour(Math.floor(i / hourSplits) + start)
85+
.minute((i % hourSplits) * 15)
86+
.toDate();
87+
const userIds = dayTimeblocks
88+
.filter((tb) => {
89+
const start = dayjs(`${tb.date} ${tb.start_time}`);
90+
const end = dayjs(`${tb.date} ${tb.end_time}`);
91+
return dayjs(currentDate).isBetween(start, end, null, '[)');
92+
})
93+
.map((tb) => tb.user_id)
94+
.filter(Boolean);
95+
const uniqueUserIds = Array.from(new Set(userIds));
96+
return uniqueUserIds.length;
97+
});
98+
const maxAvailable = Math.max(...slotAvailableCounts);
99+
if (maxAvailable > globalMaxAvailable) globalMaxAvailable = maxAvailable;
100+
});
101+
72102
return (
73103
<div
74104
id="scrollable"
@@ -84,6 +114,7 @@ export default function DayPlanners({
84114
disabled={disabled}
85115
timeblocks={timeblocks.filter((tb) => tb.date === d)}
86116
showBestTimes={showBestTimes}
117+
globalMaxAvailable={globalMaxAvailable}
87118
onBestTimesStatus={(hasBestTimes) =>
88119
handleBestTimesStatus(d, hasBestTimes)
89120
}

apps/web/src/app/[locale]/(marketing)/meet-together/plans/[planId]/day-time.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { Timeblock } from '@tuturuuu/types/primitives/Timeblock';
55
export default function DayTime({
66
editable,
77
onBestTimesStatus,
8+
globalMaxAvailable,
89
...props
910
}: {
1011
timeblocks: Timeblock[];
@@ -14,8 +15,15 @@ export default function DayTime({
1415
editable: boolean;
1516
disabled: boolean;
1617
showBestTimes?: boolean;
18+
globalMaxAvailable: number;
1719
onBestTimesStatus?: (hasBestTimes: boolean) => void;
1820
}) {
1921
if (editable) return <SelectableDayTime {...props} />;
20-
return <PreviewDayTime {...props} onBestTimesStatus={onBestTimesStatus} />;
22+
return (
23+
<PreviewDayTime
24+
{...props}
25+
globalMaxAvailable={globalMaxAvailable}
26+
onBestTimesStatus={onBestTimesStatus}
27+
/>
28+
);
2129
}

apps/web/src/app/[locale]/(marketing)/meet-together/plans/[planId]/preview-day-time.tsx

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export default function PreviewDayTime({
1919
end,
2020
disabled,
2121
showBestTimes = false,
22+
globalMaxAvailable,
2223
onBestTimesStatus,
2324
}: {
2425
timeblocks: Timeblock[];
@@ -27,6 +28,7 @@ export default function PreviewDayTime({
2728
end: number;
2829
disabled: boolean;
2930
showBestTimes?: boolean;
31+
globalMaxAvailable: number;
3032
onBestTimesStatus?: (hasBestTimes: boolean) => void;
3133
}) {
3234
const {
@@ -67,42 +69,15 @@ export default function PreviewDayTime({
6769
const uniqueUserIds = Array.from(new Set(userIds));
6870
return uniqueUserIds.length;
6971
});
70-
const maxAvailable = Math.max(...slotAvailableCounts);
7172

72-
// Find the longest contiguous block(s) with max availability
73+
// Find all blocks with the global max available
7374
const bestBlockIndices: Set<number> = new Set();
74-
if (showBestTimes && maxAvailable >= 2) {
75-
let longest = 0;
76-
let currentStart = -1;
77-
let currentLen = 0;
78-
const blocks: { start: number; len: number }[] = [];
79-
for (let i = 0; i < slotAvailableCounts.length; i++) {
80-
if (slotAvailableCounts[i] === maxAvailable) {
81-
if (currentStart === -1) currentStart = i;
82-
currentLen++;
83-
} else {
84-
if (currentLen > 0) {
85-
blocks.push({ start: currentStart, len: currentLen });
86-
if (currentLen > longest) longest = currentLen;
87-
}
88-
currentStart = -1;
89-
currentLen = 0;
75+
if (showBestTimes && globalMaxAvailable >= 2) {
76+
slotAvailableCounts.forEach((count, i) => {
77+
if (count === globalMaxAvailable) {
78+
bestBlockIndices.add(i);
9079
}
91-
}
92-
if (currentLen > 0) {
93-
blocks.push({ start: currentStart, len: currentLen });
94-
if (currentLen > longest) longest = currentLen;
95-
}
96-
// Only highlight if the longest block is more than 1 slot
97-
if (longest > 1) {
98-
blocks
99-
.filter((b) => b.len === longest)
100-
.forEach((b) => {
101-
for (let i = b.start; i < b.start + b.len; i++) {
102-
bestBlockIndices.add(i);
103-
}
104-
});
105-
}
80+
});
10681
}
10782

10883
// Notify parent about best times status

0 commit comments

Comments
 (0)