- Created comprehensive QA checklist covering edge cases (missing EXIF, timezones, codecs, corrupt files) - Added ErrorBoundary component wrapped around TimelineTree and MediaPanel - Created global error.tsx page for unhandled errors - Improved failed asset UX with red borders, warning icons, and inline error display - Added loading skeletons to TimelineTree and MediaPanel - Added retry button for failed media loads - Created DEPLOYMENT_VALIDATION.md with validation commands and checklist - Applied k8s recommendations: - Changed node affinity to required for compute nodes (Pi 5) - Enabled Tailscale LoadBalancer service for MinIO S3 (reliable Range requests) - Enabled cleanup CronJob for staging files
46 lines
1.1 KiB
TypeScript
46 lines
1.1 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { getAppName } from "@tline/config";
|
|
import { useState } from "react";
|
|
|
|
import { ErrorBoundary } from "./components/ErrorBoundary";
|
|
import { MediaPanel } from "./components/MediaPanel";
|
|
import { TimelineTree } from "./components/TimelineTree";
|
|
|
|
export default function HomePage() {
|
|
const [selectedDayIso, setSelectedDayIso] = useState<string | null>(null);
|
|
|
|
return (
|
|
<main style={{ padding: 16, display: "grid", gap: 16 }}>
|
|
<header>
|
|
<h1 style={{ marginTop: 0 }}>{getAppName()}</h1>
|
|
<ul>
|
|
<li>
|
|
<Link href="/admin">Admin</Link>
|
|
</li>
|
|
<li>
|
|
<a href="/api/healthz">API health</a>
|
|
</li>
|
|
</ul>
|
|
</header>
|
|
|
|
<div
|
|
style={{
|
|
display: "grid",
|
|
gridTemplateColumns: "2fr 1fr",
|
|
gap: 16,
|
|
alignItems: "start",
|
|
}}
|
|
>
|
|
<ErrorBoundary>
|
|
<TimelineTree onSelectDay={setSelectedDayIso} />
|
|
</ErrorBoundary>
|
|
<ErrorBoundary>
|
|
<MediaPanel selectedDayIso={selectedDayIso} />
|
|
</ErrorBoundary>
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|