feat: UI redesign with park detail pages and ride status
Some checks failed
Build and Deploy / Build & Push (push) Failing after 22s
Some checks failed
Build and Deploy / Build & Push (push) Failing after 22s
Visual overhaul: - Warmer color system with amber accent for Today, better text hierarchy - Row hover highlighting, sticky column shadow on horizontal scroll - Closed cells replaced with dot (·) instead of "Closed" text - Regional grouping (Northeast/Southeast/Midwest/Texas & South/West) - Two-row header with park count badge and WeekNav on separate lines - Amber "Today" button in WeekNav when off current week - Mobile card layout (< 1024px) with 7-day grid per park; table on desktop - Skeleton loading state via app/loading.tsx Park detail pages (/park/[id]): - Month calendar view with ← → navigation via ?month= param - Live ride status fetched from Six Flags API (cached 1h) - Ride hours only shown when they differ from park operating hours - Fallback to nearest upcoming open day when today is dropped by API, including cross-month fallback for end-of-month edge case Data layer: - Park type gains region field; parks.ts exports groupByRegion() - db.ts gains getParkMonthData() for single-park month queries - sixflags.ts gains scrapeRidesForDay() returning RidesFetchResult with rides, dataDate, isExact, and parkHoursLabel Removed: CalendarGrid.tsx, MonthNav.tsx (dead code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
interface WeekNavProps {
|
||||
weekStart: string; // YYYY-MM-DD (Sunday)
|
||||
weekStart: string; // YYYY-MM-DD (Sunday)
|
||||
weekDates: string[]; // 7 dates YYYY-MM-DD
|
||||
isCurrentWeek: boolean;
|
||||
}
|
||||
|
||||
const MONTHS = [
|
||||
@@ -29,27 +30,43 @@ function shiftWeek(weekStart: string, delta: number): string {
|
||||
return d.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
export function WeekNav({ weekStart, weekDates }: WeekNavProps) {
|
||||
export function WeekNav({ weekStart, weekDates, isCurrentWeek }: WeekNavProps) {
|
||||
const router = useRouter();
|
||||
const nav = (delta: number) =>
|
||||
router.push(`/?week=${shiftWeek(weekStart, delta)}`);
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 16 }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
<button
|
||||
onClick={() => nav(-1)}
|
||||
aria-label="Previous week"
|
||||
style={btnStyle}
|
||||
style={navBtnStyle}
|
||||
onMouseOver={(e) => Object.assign((e.target as HTMLElement).style, navBtnHover)}
|
||||
onMouseOut={(e) => Object.assign((e.target as HTMLElement).style, navBtnStyle)}
|
||||
>
|
||||
←
|
||||
</button>
|
||||
|
||||
{!isCurrentWeek && (
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
aria-label="Jump to current week"
|
||||
style={todayBtnStyle}
|
||||
onMouseOver={(e) => Object.assign((e.target as HTMLElement).style, todayBtnHover)}
|
||||
onMouseOut={(e) => Object.assign((e.target as HTMLElement).style, todayBtnStyle)}
|
||||
>
|
||||
Today
|
||||
</button>
|
||||
)}
|
||||
|
||||
<span style={{
|
||||
fontSize: "1.1rem",
|
||||
fontSize: "1rem",
|
||||
fontWeight: 600,
|
||||
color: "var(--color-text)",
|
||||
minWidth: 220,
|
||||
minWidth: 200,
|
||||
textAlign: "center",
|
||||
letterSpacing: "-0.01em",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}>
|
||||
{formatLabel(weekDates)}
|
||||
</span>
|
||||
@@ -57,7 +74,9 @@ export function WeekNav({ weekStart, weekDates }: WeekNavProps) {
|
||||
<button
|
||||
onClick={() => nav(1)}
|
||||
aria-label="Next week"
|
||||
style={btnStyle}
|
||||
style={navBtnStyle}
|
||||
onMouseOver={(e) => Object.assign((e.target as HTMLElement).style, navBtnHover)}
|
||||
onMouseOut={(e) => Object.assign((e.target as HTMLElement).style, navBtnStyle)}
|
||||
>
|
||||
→
|
||||
</button>
|
||||
@@ -65,7 +84,7 @@ export function WeekNav({ weekStart, weekDates }: WeekNavProps) {
|
||||
);
|
||||
}
|
||||
|
||||
const btnStyle: React.CSSProperties = {
|
||||
const navBtnStyle: React.CSSProperties = {
|
||||
padding: "6px 14px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid var(--color-border)",
|
||||
@@ -74,4 +93,47 @@ const btnStyle: React.CSSProperties = {
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
lineHeight: 1,
|
||||
transition: "background 150ms ease, border-color 150ms ease, color 150ms ease",
|
||||
};
|
||||
|
||||
const navBtnHover: React.CSSProperties = {
|
||||
padding: "6px 14px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid var(--color-text-dim)",
|
||||
background: "var(--color-surface-2)",
|
||||
color: "var(--color-text-secondary)",
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
lineHeight: 1,
|
||||
transition: "background 150ms ease, border-color 150ms ease, color 150ms ease",
|
||||
};
|
||||
|
||||
const todayBtnStyle: React.CSSProperties = {
|
||||
padding: "5px 12px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid var(--color-accent-muted)",
|
||||
background: "transparent",
|
||||
color: "var(--color-accent)",
|
||||
cursor: "pointer",
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: 600,
|
||||
letterSpacing: "0.04em",
|
||||
textTransform: "uppercase",
|
||||
lineHeight: 1,
|
||||
transition: "background 150ms ease, color 150ms ease",
|
||||
};
|
||||
|
||||
const todayBtnHover: React.CSSProperties = {
|
||||
padding: "5px 12px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid var(--color-accent-muted)",
|
||||
background: "var(--color-accent-muted)",
|
||||
color: "var(--color-accent-text)",
|
||||
cursor: "pointer",
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: 600,
|
||||
letterSpacing: "0.04em",
|
||||
textTransform: "uppercase",
|
||||
lineHeight: 1,
|
||||
transition: "background 150ms ease, color 150ms ease",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user