From 2889b562e64993482bd13fd806af8ed0865bab8b Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sat, 14 Feb 2026 11:52:56 +0900
Subject: refactor: migrate API from GraphQL to REST (TypeSpec/OpenAPI)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace the entire GraphQL stack (gqlgen, urql, graphql-codegen) with a
TypeSpec → OpenAPI 3.x pipeline using oapi-codegen for Go server stubs
and openapi-fetch + openapi-typescript for the frontend client.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---
 frontend/src/components/FeedSidebar.tsx | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

(limited to 'frontend/src/components/FeedSidebar.tsx')

diff --git a/frontend/src/components/FeedSidebar.tsx b/frontend/src/components/FeedSidebar.tsx
index 73d9504..4f50566 100644
--- a/frontend/src/components/FeedSidebar.tsx
+++ b/frontend/src/components/FeedSidebar.tsx
@@ -1,23 +1,35 @@
-import { useQuery } from "urql";
+import { useCallback, useEffect, useState } from "react";
 import { useLocation, useSearch } from "wouter";
-import { GetFeedsDocument } from "../graphql/generated/graphql";
+import type { components } from "../api/generated";
+import { api } from "../services/api-client";
+
+type Feed = components["schemas"]["Feed"];
 
 interface Props {
 	basePath: string;
 }
 
-const urqlContextFeed = { additionalTypenames: ["Feed", "Article"] };
-
 export function FeedSidebar({ basePath }: Props) {
 	const search = useSearch();
 	const [, setLocation] = useLocation();
 	const params = new URLSearchParams(search);
 	const selectedFeedId = params.get("feed");
 
-	const [{ data, fetching }] = useQuery({
-		query: GetFeedsDocument,
-		context: urqlContextFeed,
-	});
+	const [feeds, setFeeds] = useState<Feed[]>([]);
+	const [fetching, setFetching] = useState(true);
+
+	const fetchFeeds = useCallback(async () => {
+		setFetching(true);
+		const { data } = await api.GET("/api/feeds");
+		if (data) {
+			setFeeds(data);
+		}
+		setFetching(false);
+	}, []);
+
+	useEffect(() => {
+		fetchFeeds();
+	}, [fetchFeeds]);
 
 	const handleSelect = (feedId: string | null) => {
 		if (feedId) {
@@ -49,7 +61,7 @@ export function FeedSidebar({ basePath }: Props) {
 				{fetching && (
 					<li className="px-3 py-1.5 text-xs text-stone-400">Loading...</li>
 				)}
-				{data?.feeds.map((feed) => (
+				{feeds.map((feed) => (
 					<li key={feed.id}>
 						<button
 							type="button"
-- 
cgit v1.3-1-g0d28

