|
|
@@ -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>
|
|
|
+ );
|
|
|
+}
|