All checks were successful
Build and Deploy / Build & Push (push) Successful in 3m24s
Replace the cramped 7-column day grid with a clean open-days list. Each card now shows: - Park name + "Open today" / "Closed today" badge in the header - One row per open day (Today, Monday, Friday...) with full hours - Today row highlighted in amber; passholder days labeled inline - Whole card is a tap target linking to the park detail page Also: - Hide the legend below sm breakpoint (not needed on phones) - Reduce horizontal padding to 16px on mobile (was 24px) - Tighten MobileCardList vertical spacing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
154 lines
5.3 KiB
TypeScript
154 lines
5.3 KiB
TypeScript
import Link from "next/link";
|
||
import type { Park } from "@/lib/scrapers/types";
|
||
import type { DayData } from "@/lib/db";
|
||
|
||
interface ParkCardProps {
|
||
park: Park;
|
||
weekDates: string[]; // 7 dates YYYY-MM-DD, Sun–Sat
|
||
parkData: Record<string, DayData>;
|
||
today: string;
|
||
}
|
||
|
||
const DOW = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||
|
||
export function ParkCard({ park, weekDates, parkData, today }: ParkCardProps) {
|
||
const openDays = weekDates.filter((d) => parkData[d]?.isOpen && parkData[d]?.hoursLabel);
|
||
const isOpenToday = openDays.includes(today);
|
||
|
||
return (
|
||
<Link
|
||
href={`/park/${park.id}`}
|
||
data-park={park.name.toLowerCase()}
|
||
style={{ textDecoration: "none", display: "block" }}
|
||
>
|
||
<div style={{
|
||
background: "var(--color-surface)",
|
||
border: "1px solid var(--color-border)",
|
||
borderRadius: 12,
|
||
overflow: "hidden",
|
||
transition: "border-color 120ms ease",
|
||
}}>
|
||
{/* ── Card header ───────────────────────────────────────────────────── */}
|
||
<div style={{
|
||
padding: "14px 16px 12px",
|
||
display: "flex",
|
||
alignItems: "flex-start",
|
||
justifyContent: "space-between",
|
||
gap: 12,
|
||
}}>
|
||
<div>
|
||
<div style={{
|
||
fontSize: "0.95rem",
|
||
fontWeight: 600,
|
||
color: "var(--color-text)",
|
||
lineHeight: 1.2,
|
||
}}>
|
||
{park.name}
|
||
</div>
|
||
<div style={{
|
||
fontSize: "0.72rem",
|
||
color: "var(--color-text-muted)",
|
||
marginTop: 3,
|
||
}}>
|
||
{park.location.city}, {park.location.state}
|
||
</div>
|
||
</div>
|
||
|
||
{isOpenToday ? (
|
||
<div style={{
|
||
background: "var(--color-open-bg)",
|
||
border: "1px solid var(--color-open-border)",
|
||
borderRadius: 20,
|
||
padding: "4px 10px",
|
||
fontSize: "0.65rem",
|
||
fontWeight: 700,
|
||
color: "var(--color-open-text)",
|
||
whiteSpace: "nowrap",
|
||
flexShrink: 0,
|
||
letterSpacing: "0.03em",
|
||
}}>
|
||
Open today
|
||
</div>
|
||
) : (
|
||
<div style={{
|
||
background: "transparent",
|
||
border: "1px solid var(--color-border)",
|
||
borderRadius: 20,
|
||
padding: "4px 10px",
|
||
fontSize: "0.65rem",
|
||
fontWeight: 500,
|
||
color: "var(--color-text-muted)",
|
||
whiteSpace: "nowrap",
|
||
flexShrink: 0,
|
||
}}>
|
||
Closed today
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* ── Open days list ────────────────────────────────────────────────── */}
|
||
{openDays.length > 0 && (
|
||
<div style={{ borderTop: "1px solid var(--color-border-subtle)" }}>
|
||
{openDays.map((date, i) => {
|
||
const dow = new Date(date + "T00:00:00").getDay();
|
||
const isToday = date === today;
|
||
const dayData = parkData[date];
|
||
const isPH = dayData.specialType === "passholder_preview";
|
||
const isLast = i === openDays.length - 1;
|
||
|
||
return (
|
||
<div
|
||
key={date}
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "space-between",
|
||
padding: "9px 16px",
|
||
background: isToday ? "var(--color-today-bg)" : "transparent",
|
||
borderBottom: isLast ? "none" : "1px solid var(--color-border-subtle)",
|
||
}}
|
||
>
|
||
<span style={{
|
||
fontSize: "0.82rem",
|
||
fontWeight: isToday ? 600 : 400,
|
||
color: isToday
|
||
? "var(--color-today-text)"
|
||
: "var(--color-text-secondary)",
|
||
}}>
|
||
{isToday ? "Today" : DOW[dow]}
|
||
</span>
|
||
|
||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||
{isPH && (
|
||
<span style={{
|
||
fontSize: "0.58rem",
|
||
fontWeight: 700,
|
||
color: "var(--color-ph-label)",
|
||
letterSpacing: "0.05em",
|
||
textTransform: "uppercase",
|
||
}}>
|
||
Passholder
|
||
</span>
|
||
)}
|
||
<span style={{
|
||
fontSize: "0.82rem",
|
||
fontWeight: isToday ? 600 : 500,
|
||
color: isPH
|
||
? "var(--color-ph-hours)"
|
||
: isToday
|
||
? "var(--color-today-text)"
|
||
: "var(--color-open-hours)",
|
||
}}>
|
||
{dayData.hoursLabel}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</Link>
|
||
);
|
||
}
|