mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 08:03:26 +00:00
feat: implement search via tmdb package
This commit is contained in:
@@ -5,7 +5,7 @@ import { FontAwesome5 } from "@expo/vector-icons";
|
|||||||
|
|
||||||
import Colors from "@movie-web/tailwind-config/colors";
|
import Colors from "@movie-web/tailwind-config/colors";
|
||||||
|
|
||||||
export default function Searchbar() {
|
export default function Searchbar({ onSearchChange }: { onSearchChange: (text: string) => void }) {
|
||||||
const [keyword, setKeyword] = useState("");
|
const [keyword, setKeyword] = useState("");
|
||||||
const inputRef = useRef<TextInput>(null);
|
const inputRef = useRef<TextInput>(null);
|
||||||
|
|
||||||
@@ -22,6 +22,11 @@ export default function Searchbar() {
|
|||||||
}, []),
|
}, []),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleChange = (text: string) => {
|
||||||
|
setKeyword(text);
|
||||||
|
onSearchChange(text);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="mb-6 mt-4 flex-row items-center rounded-full border border-primary-400 focus-within:border-primary-300">
|
<View className="mb-6 mt-4 flex-row items-center rounded-full border border-primary-400 focus-within:border-primary-300">
|
||||||
<View className="ml-1 w-12 items-center justify-center">
|
<View className="ml-1 w-12 items-center justify-center">
|
||||||
@@ -29,7 +34,7 @@ export default function Searchbar() {
|
|||||||
</View>
|
</View>
|
||||||
<TextInput
|
<TextInput
|
||||||
value={keyword}
|
value={keyword}
|
||||||
onChangeText={(text) => setKeyword(text)}
|
onChangeText={handleChange}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
placeholder="What are you looking for?"
|
placeholder="What are you looking for?"
|
||||||
placeholderTextColor={Colors.secondary[200]}
|
placeholderTextColor={Colors.secondary[200]}
|
||||||
|
@@ -1,11 +1,24 @@
|
|||||||
import { ScrollView, View } from "react-native";
|
import React, { useState } from 'react';
|
||||||
|
import { ScrollView, View } from 'react-native';
|
||||||
|
|
||||||
import Item from "~/components/item/item";
|
import Item from '~/components/item/item';
|
||||||
import ScreenLayout from "~/components/layout/ScreenLayout";
|
|
||||||
import { Text } from "~/components/ui/Text";
|
import { Text } from "~/components/ui/Text";
|
||||||
import Searchbar from "./Searchbar";
|
import ScreenLayout from '~/components/layout/ScreenLayout';
|
||||||
|
import Searchbar from './Searchbar';
|
||||||
|
import { searchTitle, getMediaPoster } from '@movie-web/tmdb';
|
||||||
|
|
||||||
export default function SearchScreen() {
|
export default function SearchScreen() {
|
||||||
|
const [searchResults, setSearchResults] = useState<{ title: string; posterUrl: string; year: number; type: "movie" | "tv"; }[]>([]);
|
||||||
|
|
||||||
|
const handleSearchChange = async (query: string) => {
|
||||||
|
if (query.length > 0) {
|
||||||
|
const results = await fetchSearchResults(query);
|
||||||
|
setSearchResults(results);
|
||||||
|
} else {
|
||||||
|
setSearchResults([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<ScreenLayout
|
<ScreenLayout
|
||||||
@@ -16,19 +29,43 @@ export default function SearchScreen() {
|
|||||||
}
|
}
|
||||||
subtitle="Looking for something?"
|
subtitle="Looking for something?"
|
||||||
>
|
>
|
||||||
<Searchbar />
|
<Searchbar onSearchChange={handleSearchChange} />
|
||||||
<View className="flex w-full flex-1 flex-row flex-wrap justify-start">
|
<View className="flex w-full flex-1 flex-row flex-wrap justify-start">
|
||||||
<View className="basis-1/2 px-3 pb-3">
|
{searchResults.map((item, index) => (
|
||||||
<Item />
|
<View key={index} className="basis-1/2 px-3 pb-3">
|
||||||
</View>
|
<Item data={item} />
|
||||||
<View className="basis-1/2 px-3 pb-3">
|
</View>
|
||||||
<Item />
|
))}
|
||||||
</View>
|
|
||||||
<View className="basis-1/2 px-3 pb-3">
|
|
||||||
<Item />
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
</ScreenLayout>
|
</ScreenLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchSearchResults(query: string): Promise<{ title: string; posterUrl: string; year: number; type: "movie" | "tv"; }[]> {
|
||||||
|
console.log('Fetching results for:', query);
|
||||||
|
const results = await searchTitle(query);
|
||||||
|
|
||||||
|
return results.map((result) => {
|
||||||
|
switch (result.media_type) {
|
||||||
|
case 'movie':
|
||||||
|
return {
|
||||||
|
title: result.title,
|
||||||
|
posterUrl: getMediaPoster(result.poster_path),
|
||||||
|
year: new Date(result.release_date).getFullYear(),
|
||||||
|
type: result.media_type as "movie",
|
||||||
|
};
|
||||||
|
case 'tv':
|
||||||
|
return {
|
||||||
|
title: result.name,
|
||||||
|
posterUrl: getMediaPoster(result.poster_path),
|
||||||
|
year: new Date(result.first_air_date).getFullYear(),
|
||||||
|
type: result.media_type as "tv",
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}).filter((item): item is { title: string; posterUrl: string; year: number; type: "movie" | "tv"; } => item !== undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@@ -1,25 +1,25 @@
|
|||||||
import { Image, View } from "react-native";
|
import { Image, View } from "react-native";
|
||||||
|
|
||||||
import { TMDB_POSTER_PATH } from "~/app/constants/General";
|
|
||||||
import { Text } from "~/components/ui/Text";
|
import { Text } from "~/components/ui/Text";
|
||||||
|
|
||||||
export default function Item() {
|
export default function Item({ data }: { data: { title: string, type: string, year: number, posterUrl: string } }) {
|
||||||
|
const { title, type, year, posterUrl } = data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="w-full">
|
<View className="w-full">
|
||||||
<View className="mb-2 aspect-[9/14] w-full overflow-hidden rounded-2xl">
|
<View className="mb-2 aspect-[9/14] w-full overflow-hidden rounded-2xl">
|
||||||
<Image
|
<Image
|
||||||
source={{
|
source={{
|
||||||
uri: `${TMDB_POSTER_PATH}/w342//gdIrmf2DdY5mgN6ycVP0XlzKzbE.jpg`,
|
uri: posterUrl,
|
||||||
width: 200,
|
width: 200,
|
||||||
}}
|
}}
|
||||||
className="h-full w-full object-cover"
|
className="h-full w-full object-cover"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Text className="font-bold">Hamilton</Text>
|
<Text className="font-bold">{title}</Text>
|
||||||
<View className="flex-row items-center gap-3">
|
<View className="flex-row items-center gap-3">
|
||||||
<Text className="text-xs text-gray-600">Movie</Text>
|
<Text className="text-xs text-gray-600">{type}</Text>
|
||||||
<View className="h-1 w-1 rounded-3xl bg-gray-600" />
|
<View className="h-1 w-1 rounded-3xl bg-gray-600" />
|
||||||
<Text className="text-sm text-gray-600">2023</Text>
|
<Text className="text-sm text-gray-600">{year}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"main": "./src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@@ -5,7 +5,7 @@ const TMDB_API_KEY =
|
|||||||
"eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkYTM1ZTgyMzE4OTc0NTgxNDJmZjljZTE4ODExNWRlNiIsInN1YiI6IjY0OTM0ZDQ1ODliNTYxMDExYzliZDVhMiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.AzWnIcxPNgDwGdzeIZ_C3mRC_5_qy-Z-SRPglLjzlNc";
|
"eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkYTM1ZTgyMzE4OTc0NTgxNDJmZjljZTE4ODExNWRlNiIsInN1YiI6IjY0OTM0ZDQ1ODliNTYxMDExYzliZDVhMiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.AzWnIcxPNgDwGdzeIZ_C3mRC_5_qy-Z-SRPglLjzlNc";
|
||||||
const tmdb = new TMDB(TMDB_API_KEY);
|
const tmdb = new TMDB(TMDB_API_KEY);
|
||||||
|
|
||||||
export async function searchTitle(query: string): Promise<unknown[]> {
|
export async function searchTitle(query: string) {
|
||||||
try {
|
try {
|
||||||
const rawResults = await tmdb.search.multi({
|
const rawResults = await tmdb.search.multi({
|
||||||
query,
|
query,
|
||||||
|
Reference in New Issue
Block a user