From 376ca562d6f4d94df14b8e4c79878ee5fb4e5d9c Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Sat, 14 Mar 2026 19:33:39 +0000 Subject: [PATCH 1/2] [#68] Add error state rendering to writer and reader dashboards Fixes #68 - Surface Supabase query errors by throwing from fetch functions so useQuery captures them - Render user-visible error messages in both dashboards when queries fail Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/dashboard/reader/page.tsx | 11 +++++++++-- src/app/dashboard/writer/page.tsx | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/app/dashboard/reader/page.tsx b/src/app/dashboard/reader/page.tsx index 7e942456..0a651401 100644 --- a/src/app/dashboard/reader/page.tsx +++ b/src/app/dashboard/reader/page.tsx @@ -21,13 +21,14 @@ async function fetchDonationPage( if (!supabase) return { rows: [], totalCount: 0 }; const from = page * PAGE_SIZE; const to = from + PAGE_SIZE - 1; - const { data, count } = await supabase + const { data, count, error } = await supabase .from("donations") .select("*", { count: "exact" }) .eq("donor_address", address.toLowerCase()) .order("block_timestamp", { ascending: false }) .range(from, to) .returns(); + if (error) throw error; return { rows: data ?? [], totalCount: count ?? 0 }; } @@ -40,7 +41,7 @@ export default function ReaderDashboard() { setPage(0); }, [address]); - const { data, isLoading } = useQuery({ + const { data, isLoading, error } = useQuery({ queryKey: ["reader-donations", address, page], queryFn: () => fetchDonationPage(address!, page), enabled: isConnected && !!address, @@ -100,6 +101,12 @@ export default function ReaderDashboard() { {isLoading &&

Loading...

} + {error && ( +

+ Failed to load donations. Please try again. +

+ )} +
{donations.map((d) => ( diff --git a/src/app/dashboard/writer/page.tsx b/src/app/dashboard/writer/page.tsx index 17e26eb3..47eb301d 100644 --- a/src/app/dashboard/writer/page.tsx +++ b/src/app/dashboard/writer/page.tsx @@ -11,20 +11,21 @@ async function fetchWriterStorylines( address: string, ): Promise { if (!supabase) return []; - const { data } = await supabase + const { data, error } = await supabase .from("storylines") .select("*") .eq("writer_address", address.toLowerCase()) .eq("hidden", false) .order("block_timestamp", { ascending: false }) .returns(); + if (error) throw error; return data ?? []; } export default function WriterDashboard() { const { address, isConnected } = useAccount(); - const { data: storylines = [], isLoading } = useQuery({ + const { data: storylines = [], isLoading, error } = useQuery({ queryKey: ["writer-storylines", address], queryFn: () => fetchWriterStorylines(address!), enabled: isConnected && !!address, @@ -53,6 +54,12 @@ export default function WriterDashboard() { {isLoading &&

Loading...

} + {error && ( +

+ Failed to load storylines. Please try again. +

+ )} +
{storylines.map((s) => ( From 5c413bf8557b5f5dac98c44390cf1ae32cd6ad41 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Sat, 14 Mar 2026 19:35:46 +0000 Subject: [PATCH 2/2] [#68] Gate empty-state rendering on !error Prevents showing both error message and "No storylines/donations yet" simultaneously when a query fails. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/dashboard/reader/page.tsx | 2 +- src/app/dashboard/writer/page.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/reader/page.tsx b/src/app/dashboard/reader/page.tsx index 0a651401..61a0da82 100644 --- a/src/app/dashboard/reader/page.tsx +++ b/src/app/dashboard/reader/page.tsx @@ -111,7 +111,7 @@ export default function ReaderDashboard() { {donations.map((d) => ( ))} - {!isLoading && donations.length === 0 && ( + {!isLoading && !error && donations.length === 0 && (

No donations yet.

diff --git a/src/app/dashboard/writer/page.tsx b/src/app/dashboard/writer/page.tsx index 47eb301d..929a08c0 100644 --- a/src/app/dashboard/writer/page.tsx +++ b/src/app/dashboard/writer/page.tsx @@ -64,7 +64,7 @@ export default function WriterDashboard() { {storylines.map((s) => ( ))} - {!isLoading && storylines.length === 0 && ( + {!isLoading && !error && storylines.length === 0 && (

No storylines yet.