feat: Add hour titles, make list titles sticky

This commit is contained in:
Matej Stieranka 2025-07-03 15:06:48 +02:00
parent 6110d965a6
commit 6288e716d0
8 changed files with 64 additions and 45 deletions

View file

@ -1,4 +1,4 @@
import { groupEventsByLine } from "@/common/utils";
import { groupEventsByLine, groupEventsByStartTime } from "@/common/utils";
import { EventCard } from "@/components/EventCard";
import { EventList } from "@/components/EventList";
import { Button } from "@/components/ui/button";
@ -11,6 +11,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { getAllLines, getEventsForDate } from "@/db";
import { line } from "drizzle-orm/pg-core";
import { notFound } from "next/navigation";
export default async function ScheduleByDate({
@ -35,11 +36,12 @@ export default async function ScheduleByDate({
if (events.length === 0) {
return notFound();
}
const groupedEvents = groupEventsByLine(events);
const eventsByLine = groupEventsByLine(events);
const eventsByTime = groupEventsByStartTime(events);
const allLines = await getAllLines();
return (
<div className="flex flex-col items-center justify-items-center p-8 pb-20 gap-4 sm:p-20 w-full">
<div className="flex flex-col sm:flex-row justify-between items-center w-full gap-2 mb-4">
<div className="flex flex-col items-center justify-items-center pb-20 w-full">
<div className="flex flex-col sm:flex-row justify-between items-center w-full gap-2 p-8">
<h1 className="text-3xl font-bold">
{parsedDate.toLocaleDateString(["cs-CZ"], {
weekday: "long",
@ -71,14 +73,25 @@ export default async function ScheduleByDate({
</div>
<main className="flex flex-col gap-8 items-center">
{group === "line" &&
groupedEvents.map((line) => (
eventsByLine.map((line) => (
<EventList
key={line.lineId}
events={line.events}
title={allLines.find((l) => l.id === line.lineId)?.name}
/>
))}
{group !== "line" && <EventList events={events} showLine />}
{group !== "line" &&
eventsByTime.map((time) => (
<EventList
key={time.startTime.toISOString()}
events={time.events}
title={`Od ${time.startTime.toLocaleTimeString("cs-CZ", {
hour12: false,
hour: "numeric",
minute: "2-digit",
})}`}
/>
))}
</main>
</div>
);

View file

@ -23,8 +23,8 @@ export default async function FavoritesPage({
});
return (
<div className="flex flex-col items-center justify-items-center p-8 pb-20 gap-4 sm:p-20 w-full">
<div className="flex flex-col sm:flex-row justify-between items-center w-full gap-2 mb-4">
<div className="flex flex-col items-center justify-items-center pb-20 w-full">
<div className="flex flex-col sm:flex-row justify-between items-center w-full gap-2 p-8">
<h1 className="text-3xl font-bold">Oblíbené</h1>
<ShowElapsedSwitch defaultValue={false} />
</div>

View file

@ -38,7 +38,7 @@ export default async function RootLayout({
<SidebarProvider>
<AppSidebar />
<SidebarInset>
<header className="bg-background sticky top-0 flex h-16 shrink-0 items-center gap-2 border-b px-4">
<header className="bg-background sticky top-0 flex h-16 shrink-0 z-10 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator orientation="vertical" className="mr-2 h-4" />
<div className="flex-grow">

View file

@ -23,7 +23,7 @@ export default async function ScheduleByLine({
const lineData = groupEventsByDate(events);
return (
<div className="flex flex-col items-center justify-items-center p-8 pb-20 gap-4 sm:p-20 w-full">
<div className="flex flex-col items-center justify-items-center pb-20 w-full">
<div className="flex flex-col items-center text-center">
<h1 className="text-3xl font-bold mb-4">{lineInfo.name}</h1>
<h6 className="text-gray-500 mb-4">{lineInfo.description}</h6>

View file

@ -7,21 +7,23 @@ export default async function FavoritesPage() {
const groupedEvents = groupEventsByStartTime(nowEvents);
return (
<div className="flex flex-col items-center justify-items-center p-8 pb-20 gap-4 sm:p-20 w-full">
<div className="flex flex-col sm:flex-row justify-between items-center w-full gap-2 mb-4">
<div className="flex flex-col items-center justify-items-center pb-20 w-full">
<div className="flex flex-col sm:flex-row justify-between items-center w-full gap-2 p-8">
<h1 className="text-3xl font-bold">Kam jít?</h1>
</div>
<main className="flex flex-col gap-8 w-full">
{groupedEvents.map(({events, startTime}) => (
{groupedEvents.map(({ events, startTime }) => (
<div key={startTime.toISOString()} className="w-full">
<h2 className="text-2xl font-semibold mb-4">
Od {new Date(startTime).toLocaleTimeString("cs-CZ", {
<EventList
title={`Od ${new Date(startTime).toLocaleTimeString("cs-CZ", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
})}
</h2>
<EventList events={events} showDate showLine />
})}`}
events={events}
showDate
showLine
/>
</div>
))}
</main>

View file

@ -13,7 +13,7 @@ export default async function Home({ searchParams }: HomePageProps) {
console.log("Message from searchParams:", message);
return (
<div className="flex flex-col items-center justify-items-center p-8 pb-20 gap-4 sm:p-20 w-full">
<div className="flex flex-col items-center justify-items-center pb-20 w-full">
<main className="flex flex-col gap-[32px] w-full items-center sm:items-start">
{message && (
<Alert variant="default">

View file

@ -10,7 +10,7 @@ export default async function SearchPage({ searchParams }: SearchPageProps) {
const query = (await searchParams).q || "";
const results = query ? await searchEvents(query) : [];
return (
<div className="flex flex-col items-center justify-items-center p-8 pb-20 gap-4 sm:p-20 w-full">
<div className="flex flex-col items-center justify-items-center pb-20 w-full">
<main className="flex flex-col gap-8 items-center w-full">
<h1 className="text-3xl font-bold mb-4 w-full">
Výsledky hledání pro "{query}"

View file

@ -2,30 +2,34 @@ import type { Event } from "@/common/parser";
import { EventCard } from "./EventCard";
export function EventList({
events,
title,
showDate,
showLine,
events,
title,
showDate,
showLine,
}: {
events: Event[];
title?: string;
showDate?: boolean;
showLine?: boolean;
events: Event[];
title?: string;
showDate?: boolean;
showLine?: boolean;
}) {
return (
<div className="space-y-2 w-full">
{title && <h2 className="text-2xl font-bold">{title}</h2>}
{events.length === 0 && (
<p className="text-gray-500">Žádné události.</p>
)}
{events.map((event) => (
<EventCard
key={event.id}
event={event}
showDate={showDate}
showLine={showLine}
/>
))}
</div>
);
}
return (
<div className="space-y-2 w-full">
{title && (
<h2 className="text-2xl font-bold sticky top-16 bg-white dark:bg-black px-8 py-4">
{title}
</h2>
)}
{events.length === 0 && <p className="text-gray-500 px-8">Žádné události.</p>}
<div className="flex flex-col gap-2 px-8">
{events.map((event) => (
<EventCard
key={event.id}
event={event}
showDate={showDate}
showLine={showLine}
/>
))}
</div>
</div>
);
}