Skip to content

Commit

Permalink
Add /tv, fix #3
Browse files Browse the repository at this point in the history
  • Loading branch information
cak committed Jul 28, 2024
1 parent fa67bde commit 55a0e8e
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 0 deletions.
66 changes: 66 additions & 0 deletions app/src/components/clock/TVClock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import localFont from "next/font/local";
import { useEffect, useState } from "react";
import React from "react";

const latoFont = localFont({
src: "../../../public/fonts/lato.woff2",
display: "swap",
variable: "--font-lato",
});

function padTime(num: number): string {
return num.toString().padStart(2, "0");
}

function TVClock() {
const [time, setTime] = useState({
hours: 0,
minutes: 0,
seconds: 0,
});

useEffect(() => {
const updateClock = setInterval(() => {
const date = new Date(
new Date().toLocaleString("en-US", {
timeZone: "America/Los_Angeles",
})
);
setTime({
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
});
}, 100);
return () => {
clearInterval(updateClock);
};
}, []);

return (
<div className="grid place-items-center text-center mx-5">
<div className="grid grid-flow-col gap-4 md:gap-12 text-center md:auto-cols-max">
<div>
<span className="font-bold text-xl sm:text-2xl md:text-4xl lg:text-7xl text-dc-teal mr-1 font-mono">
{padTime(time.hours)}
</span>
<span className={latoFont.className}>hours</span>
</div>
<div>
<span className="font-bold text-xl sm:text-2xl md:text-4xl lg:text-7xl text-dc-yellow mr-1 font-mono ">
{padTime(time.minutes)}
</span>
<span className={latoFont.className}>minutes</span>
</div>
<div>
<span className="font-bold text-xl sm:text-2xl md:text-4xl lg:text-7xl text-dc-red mr-1 font-mono">
{padTime(time.seconds)}
</span>
<span className={latoFont.className}>seconds</span>
</div>
</div>
</div>
);
}

export default TVClock;
8 changes: 8 additions & 0 deletions app/src/components/tv/TV.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import TVEvents from "./TVEvents";
import React from "react";

function TV({ events }: { events: EventData[] }) {
return <TVEvents events={events} />;
}

export default TV;
36 changes: 36 additions & 0 deletions app/src/components/tv/TVEventCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { eventTime } from "@/lib/utils/dates";
import React from "react";

function TVEventCell({ event }: { event: EventData }) {
return (
<div className="my-3 ml-2 mr-3">
<div className="items-center h-min-36 table">
<div
className={`table-cell px-2 h-full w-3 bg-[${event.color}] rounded-md`}
/>
<div className="ml-5">
<div className="w-full table-cell">
<h1 className="text-3xl font-bold text-left break-words">
{event.title}
</h1>

<p className="text-lg">{event.speakers}</p>

<p className="text-xl text-gray-400">{event.location}</p>
<div
className={`rounded-full h-3 w-3 inline-flex mr-2 bg-[${event.color}]`}
/>
<p className="text-base inline-flex">{event.category}</p>
<p className="text-xl text-dc-yellow font-bold">
{`${eventTime(new Date(event.begin), false)} - ${eventTime(
new Date(event.end)
)}`}
</p>
</div>
</div>
</div>
</div>
);
}

export default TVEventCell;
133 changes: 133 additions & 0 deletions app/src/components/tv/TVEvents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import TVClock from "../clock/TVClock";
import TVEventCell from "./TVEventCell";
import localFont from "next/font/local";
import Theme from "@/lib/utils/theme";
import { dateGroupTitle, eventDay } from "@/lib/utils/dates";
import React from "react";

const dcFont = localFont({
src: "../../../public/fonts/lato.woff2",
display: "swap",
variable: "--font-freeway",
});

function TVEvents({ events }: { events: EventData[] }) {
const [filteredEvents, setFilteredEvents] = useState<
Map<string, EventData[]>
>(new Map());

const theme = new Theme();
const router = useRouter();
const { l, t, debug } = router.query;

useEffect(() => {
const groupedDates = (
displayEvents: EventData[]
): Map<string, EventData[]> =>
displayEvents
.sort((a, b) => a.beginTimestampSeconds - b.beginTimestampSeconds)
.reduce((group, e) => {
const day = eventDay(new Date(e.begin));
const groups = group.get(day) ?? [];
groups.push(e);
group.set(day, groups);
return group;
}, new Map<string, EventData[]>());

const filterEvents = () => {
const filterTag = Number(l) || 46166;

return groupedDates(
events.filter((e) => {
if (!e.tags.map((t) => t.id).includes(filterTag)) {
return false;
}

const future = new Date();
// eslint-disable-next-line no-constant-binary-expression
const hoursToAdd = Number(t ?? 6) ?? 6;
future.setHours(future.getHours() + hoursToAdd);

const now = new Date();

const begin = new Date(e.begin).getTime();

if (begin >= now.getTime() && begin <= future.getTime()) {
return true;
}

return debug ? true : false;
})
);
};

setFilteredEvents(filterEvents());

const pageScroll = () => {
window.scrollBy({
top: 45,
left: 0,
behavior: "smooth",
});
};

const scrollPageInt = setInterval(() => {
setFilteredEvents(filterEvents());
const scroll = setInterval(() => {
pageScroll();
}, 900);
setTimeout(() => {
window.scrollTo({ top: 0, behavior: "smooth" });
clearInterval(scroll);
}, 70000);
}, 70100);
return () => {
clearInterval(scrollPageInt);
};
}, [events, l, t]);

console.log(filteredEvents);
return (
<div className="flex justify-end mb-2 mr-14 ml-5">
<div className="flex-initial w-full mr-2">
{Array.from(filteredEvents).map(([day, dayEvents]) => (
<div key={day}>
<div className="date-events">
<div
className={`border-4 border-white bg-${theme.nextColor} rounded-b-lg`}
>
<p className="text-gray-light text-4xl p-2 ml-1">
{dateGroupTitle(day)}
</p>
</div>
{dayEvents
.sort(
(a, b) => a.beginTimestampSeconds - b.beginTimestampSeconds
)
.map((event) => (
<div className="event" key={event.id} aria-hidden="true">
<TVEventCell event={event} />
</div>
))}
</div>
</div>
))}
</div>
<div className="flex-initial ml-5 mt-4">
<div className="sticky top-36 z-100">
<p
className={`text-center text-9xl mb-10 font-bold ${dcFont.className}`}
>
NFO Node
</p>
<p className="text-xl">Current time:</p>
<TVClock />
</div>
</div>
</div>
);
}

export default TVEvents;
47 changes: 47 additions & 0 deletions app/src/pages/tv/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Head from "next/head";
import TV from "../../components/tv/TV";
import useSWR from "swr";
import Loading from "@/components/misc/Loading";
import Error from "@/components/misc/Error";
import React from "react";
import { fetcher, toEventsData } from "@/lib/utils/misc";

export default function TVPage() {
const { data, error, isLoading } = useSWR<HTEvent[], Error>(
"/ht/events.json",
fetcher
);

const { data: tags, isLoading: tagsIsLoading } = useSWR<HTTag[], Error>(
"/ht/tags.json",
fetcher
);

if (isLoading || tagsIsLoading) {
return <Loading />;
}

if (data === undefined || error !== undefined) {
return <Error />;
}

const events = toEventsData(data, tags ?? []);

return (
<div>
<Head>
<title>Info Booth</title>
<meta name="description" content="Info Booth" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1"
/>
<link rel="icon" href="/favicon.ico" />
</Head>

<main className="mb-20">
<TV events={events} />
</main>
</div>
);
}

0 comments on commit 55a0e8e

Please sign in to comment.