ソースを参照

feat: add MovieSearchPanel composition component

Composes SearchBar + SearchResults + useMovieSearch + useAddMovie into
a self-contained client component for the movie list page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
User 2 ヶ月 前
コミット
6df4eb8cc8
1 ファイル変更54 行追加0 行削除
  1. 54 0
      src/components/movies/movie-search-panel.tsx

+ 54 - 0
src/components/movies/movie-search-panel.tsx

@@ -0,0 +1,54 @@
+"use client";
+
+import { useState, useCallback } from "react";
+import { SearchBar } from "./search-bar";
+import { SearchResults } from "./search-results";
+import { useMovieSearch } from "@/hooks/use-movie-search";
+import { useAddMovie } from "@/hooks/use-add-movie";
+import type { Database } from "@/types/database";
+
+type MovieRow = Database["public"]["Tables"]["movies"]["Row"];
+
+interface MovieSearchPanelProps {
+  groupId: string;
+  groupMovies: MovieRow[];
+}
+
+export function MovieSearchPanel({ groupId, groupMovies }: MovieSearchPanelProps) {
+  const [searchQuery, setSearchQuery] = useState("");
+  const [addingTmdbId, setAddingTmdbId] = useState<number | null>(null);
+
+  const { data, isLoading } = useMovieSearch(searchQuery);
+  const tmdbResults = data?.results ?? [];
+
+  const addMovie = useAddMovie();
+
+  const handleAdd = useCallback(
+    (tmdbId: number) => {
+      setAddingTmdbId(tmdbId);
+      addMovie.mutate(
+        { tmdb_id: tmdbId, group_id: groupId },
+        { onSettled: () => setAddingTmdbId(null) },
+      );
+    },
+    [addMovie, groupId],
+  );
+
+  return (
+    <div className="space-y-3">
+      <SearchBar onSearch={setSearchQuery} isLoading={isLoading} />
+      {searchQuery.length >= 2 && (
+        <div className="max-h-96 overflow-y-auto rounded-lg border border-gray-200 bg-white p-3 dark:border-gray-700 dark:bg-gray-800">
+          <SearchResults
+            tmdbResults={tmdbResults}
+            groupMovies={groupMovies}
+            query={searchQuery}
+            isAdding={addMovie.isPending}
+            addingTmdbId={addingTmdbId}
+            onAdd={handleAdd}
+          />
+        </div>
+      )}
+    </div>
+  );
+}