fix(projects): surface API errors instead of silently rendering empty list
Made-with: Cursor
This commit is contained in:
@@ -73,6 +73,7 @@ export default function ProjectsPage() {
|
||||
|
||||
const [projects, setProjects] = useState<ProjectWithStats[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
const [showNew, setShowNew] = useState(false);
|
||||
const [projectToDelete, setProjectToDelete] = useState<ProjectWithStats | null>(null);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
@@ -81,12 +82,20 @@ export default function ProjectsPage() {
|
||||
const fetchProjects = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await fetch("/api/projects");
|
||||
if (!res.ok) throw new Error("Failed to fetch projects");
|
||||
setLoadError(null);
|
||||
const res = await fetch("/api/projects", { credentials: "include" });
|
||||
if (res.status === 401) {
|
||||
throw new Error("Your session expired — please log in again.");
|
||||
}
|
||||
if (!res.ok) {
|
||||
let body: { error?: string; details?: string } = {};
|
||||
try { body = await res.json(); } catch { /* keep {} */ }
|
||||
throw new Error(body.error || `HTTP ${res.status} ${res.statusText}`.trim());
|
||||
}
|
||||
const data = await res.json();
|
||||
setProjects(data.projects ?? []);
|
||||
} catch {
|
||||
/* silent */
|
||||
} catch (err) {
|
||||
setLoadError(err instanceof Error ? err.message : "Failed to load projects");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -174,6 +183,29 @@ export default function ProjectsPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Error */}
|
||||
{!loading && loadError && (
|
||||
<div style={{
|
||||
marginBottom: 24, padding: "14px 18px",
|
||||
background: "#fdecea", border: "1px solid #f4c4be",
|
||||
borderRadius: 10, color: "#8b2a1f", fontSize: "0.85rem",
|
||||
display: "flex", alignItems: "center", gap: 12,
|
||||
}}>
|
||||
<span style={{ flex: 1 }}>{loadError}</span>
|
||||
<button
|
||||
onClick={fetchProjects}
|
||||
style={{
|
||||
padding: "5px 12px", borderRadius: 6,
|
||||
background: "#8b2a1f", color: "#fff", border: "none",
|
||||
fontSize: "0.78rem", fontWeight: 600, cursor: "pointer",
|
||||
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif",
|
||||
}}
|
||||
>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Project list */}
|
||||
{!loading && (
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
||||
|
||||
Reference in New Issue
Block a user