Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
393 changes: 248 additions & 145 deletions client/app/components/SearchMovieModal/SearchMovieModal.tsx

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/app/components/SearchMovieModal/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { default } from './SearchMovieModal';
export type { SearchParams } from './SearchMovieModal';
export type { SearchParams, SearchType } from './SearchMovieModal';
85 changes: 82 additions & 3 deletions client/app/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export async function deleteMovie(id: string): Promise<{ success: boolean; error
*/
export async function createMovie(movieData: Omit<Movie, '_id'>): Promise<{ success: boolean; error?: string; movieId?: string }> {
try {
const response = await fetch(`${API_BASE_URL}/api/movies/`, {
const response = await fetch(`${API_BASE_URL}/api/movies`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand Down Expand Up @@ -276,7 +276,7 @@ export async function deleteMoviesBatch(movieIds: string[]): Promise<{ success:
}
};

const response = await fetch(`${API_BASE_URL}/api/movies/`, {
const response = await fetch(`${API_BASE_URL}/api/movies`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Expand Down Expand Up @@ -326,7 +326,7 @@ export async function updateMoviesBatch(movieIds: string[], updateData: Partial<
}
};

const response = await fetch(`${API_BASE_URL}/api/movies/`, {
const response = await fetch(`${API_BASE_URL}/api/movies`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Expand Down Expand Up @@ -437,3 +437,82 @@ export async function searchMovies(searchParams: {
};
}
}

/**
* Search movies using MongoDB Vector Search to find movies with similar plots
*/
export async function vectorSearchMovies(searchParams: {
q: string;
limit?: number;
}): Promise<{ success: boolean; error?: string; movies?: Movie[]; results?: any[] }> {
try {
const limit = searchParams.limit || 10;

const queryParams = new URLSearchParams();
queryParams.append('q', searchParams.q);
queryParams.append('limit', limit.toString());

const response = await fetch(`${API_BASE_URL}/api/movies/vector-search?${queryParams}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

const result = await response.json();

if (!response.ok) {
return {
success: false,
error: result.error || `Failed to perform vector search: ${response.status}`
};
}

if (!result.success) {
return {
success: false,
error: result.error || 'API returned error response'
};
}

// Transform VectorSearchResult objects to Movie objects for backend compatibility
const movies: Movie[] = (result.data || []).map((item: any) => {
// Convert VectorSearchResult to Movie format
return {
_id: item._id || item.id, // Handle both _id (Python) and id (Java) field names
title: item.title || '',
plot: item.plot || '',
poster: item.poster,
year: item.year,
genres: item.genres || [],
directors: item.directors || [],
cast: item.cast || [],
// Add default values for fields not included in VectorSearchResult
fullplot: undefined,
released: undefined,
runtime: undefined,
writers: [],
countries: [],
languages: [],
rated: undefined,
awards: undefined,
imdb: undefined,
tomatoes: undefined,
metacritic: undefined,
type: undefined
} as Movie;
});

return {
success: true,
movies,
results: result.data || []
};
} catch (error) {
console.error('Error performing vector search:', error);
return {
success: false,
error: 'Network error occurred while performing vector search'
};
}
}
11 changes: 11 additions & 0 deletions client/app/movies/movies.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@
text-align: center;
}

.searchInfo {
margin: 2rem 0;
padding: 1rem;
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
text-align: center;
font-size: 0.9rem;
color: #666;
}

.selectAllButton {
padding: 0.5rem 1rem;
background: #6c757d;
Expand Down
Loading
Loading