From 2fb6471a685bec1433be3335f377a1a2313e4820 Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Thu, 1 Jan 2026 23:44:50 +0900
Subject: refactor(client): migrate API calls to typed RPC client
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace raw fetch() calls with apiClient.rpc typed client across all
modal and page components. This provides better type safety and
eliminates manual auth header handling.

- Make handleResponse public for component usage
- Update all component tests to mock RPC methods instead of fetch
- Change POSTGRES_HOST default to kioku-db for Docker compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---
 src/client/pages/DeckDetailPage.tsx | 42 ++++++-------------------------------
 1 file changed, 6 insertions(+), 36 deletions(-)

(limited to 'src/client/pages/DeckDetailPage.tsx')

diff --git a/src/client/pages/DeckDetailPage.tsx b/src/client/pages/DeckDetailPage.tsx
index 3741111..f9b50f2 100644
--- a/src/client/pages/DeckDetailPage.tsx
+++ b/src/client/pages/DeckDetailPage.tsx
@@ -233,50 +233,20 @@ export function DeckDetailPage() {
 	const fetchDeck = useCallback(async () => {
 		if (!deckId) return;
 
-		const authHeader = apiClient.getAuthHeader();
-		if (!authHeader) {
-			throw new ApiClientError("Not authenticated", 401);
-		}
-
-		const res = await fetch(`/api/decks/${deckId}`, {
-			headers: authHeader,
+		const res = await apiClient.rpc.api.decks[":id"].$get({
+			param: { id: deckId },
 		});
-
-		if (!res.ok) {
-			const errorBody = await res.json().catch(() => ({}));
-			throw new ApiClientError(
-				(errorBody as { error?: string }).error ||
-					`Request failed with status ${res.status}`,
-				res.status,
-			);
-		}
-
-		const data = await res.json();
+		const data = await apiClient.handleResponse<{ deck: Deck }>(res);
 		setDeck(data.deck);
 	}, [deckId]);
 
 	const fetchCards = useCallback(async () => {
 		if (!deckId) return;
 
-		const authHeader = apiClient.getAuthHeader();
-		if (!authHeader) {
-			throw new ApiClientError("Not authenticated", 401);
-		}
-
-		const res = await fetch(`/api/decks/${deckId}/cards`, {
-			headers: authHeader,
+		const res = await apiClient.rpc.api.decks[":deckId"].cards.$get({
+			param: { deckId },
 		});
-
-		if (!res.ok) {
-			const errorBody = await res.json().catch(() => ({}));
-			throw new ApiClientError(
-				(errorBody as { error?: string }).error ||
-					`Request failed with status ${res.status}`,
-				res.status,
-			);
-		}
-
-		const data = await res.json();
+		const data = await apiClient.handleResponse<{ cards: Card[] }>(res);
 		setCards(data.cards);
 	}, [deckId]);
 
-- 
cgit v1.2.3-70-g09d2

