Skip to content

Commit

Permalink
small performance optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
cak committed Sep 5, 2024
1 parent 7f417da commit 04ff9a0
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 68 deletions.
6 changes: 5 additions & 1 deletion src/components/event/Event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ function Event({
</div>
<div className="inline-grid grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-0 md:gap-1 gap-y-2 md:gap-y-3 w-10/12">
{eventTags
?.sort((a, b) => (a.sort_order > b.sort_order ? 1 : -1))
.sort((a, b) =>
a.sort_order !== b.sort_order
? a.sort_order - b.sort_order
: a.label.localeCompare(b.label)
)
?.map((tag) => (
<div
className="flex items-center mr-3 md:mr-4 lg:mr-5"
Expand Down
50 changes: 27 additions & 23 deletions src/components/schedule/EventCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ export default function EventCell({
const router = useRouter();
const eventUrl = `../event?conf=${conf}&event=${event.id}`;

const handleRowClick = () => {
router.push(eventUrl);
};

return (
<TableRow
id={`e-${event.id}`}
className="cursor-pointer"
onClick={() => router.push(eventUrl)}
onClick={handleRowClick}
>
<TableCell className="relative align-middle">
<div
className="absolute top-1 bottom-1 left-1 w-1 md:w-2 lg:w-3 rounded"
style={{ background: event.color }}
style={{ backgroundColor: event.color }}
/>
</TableCell>
<TableCell className="align-middle">
Expand All @@ -32,32 +36,32 @@ export default function EventCell({
<p className="text-xs md:text-sm">{eventTimeTable(event.end)}</p>
</TableCell>
<TableCell className="align-middle">
<div>
<a href={eventUrl}>
<h1 className="text-sm md:text-base font-bold break-words max-w-96 drop-shadow-sm ">
{event.title}
</h1>
<p className="text-xs md:text-sm mt-1 italic">{event.speakers}</p>
</a>
</div>
<a href={eventUrl}>
<h1 className="text-sm md:text-base font-bold break-words max-w-96 drop-shadow-sm">
{event.title}
</h1>
<p className="text-xs md:text-sm mt-1 italic">{event.speakers}</p>
</a>
</TableCell>
<TableCell className="align-middle">
<p className="text-xs md:text-sm">{event.location}</p>
</TableCell>
<TableCell className="align-middle">
<div>
{event.tags
?.sort((a, b) => (a.sort_order > b.sort_order ? 1 : -1))
?.map((tag) => (
<div className="flex mr-2" key={tag.id}>
<span
style={{ backgroundColor: tag.color_background }}
className="rounded-full h-2 w-2 green inline-flex flex-none m-1"
/>
<p className="text-xs">{tag.label}</p>
</div>
))}
</div>
{event.tags
?.sort((a, b) =>
a.sort_order !== b.sort_order
? a.sort_order - b.sort_order
: a.label.localeCompare(b.label)
)
.map((tag) => (
<div className="flex mr-2" key={tag.id}>
<span
style={{ backgroundColor: tag.color_background }}
className="rounded-full h-2 w-2 inline-flex flex-none m-1"
/>
<p className="text-xs">{tag.label}</p>
</div>
))}
</TableCell>
</TableRow>
);
Expand Down
117 changes: 73 additions & 44 deletions src/components/schedule/EventsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,27 @@ import {
TableRow,
} from "../ui/table";
import EventCell from "./EventCell";
import React, { useEffect, useRef, useState } from "react";
import React, { useEffect, useRef, useState, useMemo } from "react";
import { Button } from "../ui/button";

const DayButton = ({
day,
isActive,
onClick,
}: {
day: string;
isActive: boolean;
onClick: () => void;
}) => (
<Button
className="mx-1"
variant={isActive ? "default" : "outline"}
onClick={onClick}
>
{tabDateTitle(day)}
</Button>
);

export default function EventsTable({
dateGroup,
conf,
Expand All @@ -22,6 +40,17 @@ export default function EventsTable({
const dayRefs = useRef(new Map<string, HTMLDivElement>());
const [activeDay, setActiveDay] = useState<string | null>(null);

const filteredDateGroup = useMemo(() => {
return Array.from(dateGroup)
.map(([day, events]) => {
const filteredEvents = events.filter(
(e) => selectedTag === 0 || e.tags?.some((t) => t.id === selectedTag)
);
return { day, filteredEvents };
})
.filter(({ filteredEvents }) => filteredEvents.length > 0);
}, [dateGroup, selectedTag]);

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
Expand All @@ -43,48 +72,40 @@ export default function EventsTable({
return () => {
observer.disconnect();
};
}, []);
}, [filteredDateGroup]);

const scrollToDay = (day: string) => {
const dayRow = dayRefs.current.get(day);
if (dayRow) {
const headerOffset = 120;
const elementPosition = dayRow.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.scrollY - headerOffset;

window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
}
};
if (!dayRow) return; // Ensure dayRow exists

const filteredDateGroup = Array.from(dateGroup)
.map(([day, events]) => {
const filteredEvents = events.filter(
(e) => selectedTag === 0 || e.tags?.some((t) => t.id == selectedTag)
);
const headerOffset = 120;
const elementPosition = dayRow.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.scrollY - headerOffset;

return { day, filteredEvents };
})
.filter(({ filteredEvents }) => filteredEvents.length > 0);
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
};

return (
<div>
{/* Day buttons */}
<div
className="py-2 flex justify-center sticky top-[60px] bg-background z-10"
style={{ height: "60px" }}
>
{filteredDateGroup.map(({ day }) => (
<Button
className="mx-1"
variant={activeDay === day ? "default" : "outline"}
<DayButton
key={day}
day={day}
isActive={activeDay === day}
onClick={() => scrollToDay(day)}
>
{tabDateTitle(day)}
</Button>
/>
))}
</div>

{/* Event day sections */}
{filteredDateGroup.map(({ day, filteredEvents }) => (
<React.Fragment key={day}>
<div
Expand All @@ -99,23 +120,31 @@ export default function EventsTable({
{eventDayTable(day)}
</h2>
</div>
<Table className="w-full mb-10">
<TableHeader>
<TableRow>
<TableHead />
<TableHead>Start</TableHead>
<TableHead className="md:table-cell hidden">End</TableHead>
<TableHead>Event</TableHead>
<TableHead>Location</TableHead>
<TableHead>Tags</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredEvents.map((htEvent) => (
<EventCell key={htEvent.id} conf={conf.code} event={htEvent} />
))}
</TableBody>
</Table>

{/* Event table */}
{filteredEvents.length > 0 && (
<Table className="w-full mb-10">
<TableHeader>
<TableRow>
<TableHead />
<TableHead>Start</TableHead>
<TableHead className="md:table-cell hidden">End</TableHead>
<TableHead>Event</TableHead>
<TableHead>Location</TableHead>
<TableHead>Tags</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredEvents.map((htEvent) => (
<EventCell
key={htEvent.id}
conf={conf.code}
event={htEvent}
/>
))}
</TableBody>
</Table>
)}
</React.Fragment>
))}
</div>
Expand Down

0 comments on commit 04ff9a0

Please sign in to comment.