add upload and search implemented

This commit is contained in:
dimitar 2025-02-12 09:07:21 +01:00
parent f3007d6419
commit 3aeffb3585
3 changed files with 71 additions and 23 deletions

View File

@ -19,27 +19,32 @@ import { useEffect, useState } from "react";
import { getCars, getFeaturedCars } from "@/lib/database"; import { getCars, getFeaturedCars } from "@/lib/database";
export default function Index() { export default function Index() {
const { user, refetch } = useGlobalContext(); const { user } = useGlobalContext();
const [cars, setCars] = useState<any[]>([]); const [cars, setCars] = useState<any[]>([]);
const [featuredCars, setFeaturedCars] = useState<any[]>([]); const [featuredCars, setFeaturedCars] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState(false);
const fetchCars = async (query?: string) => {
try {
setIsLoading(true);
const fetchedCars = await getCars(query);
setCars(fetchedCars);
} catch (error) {
console.error('Error fetching cars:', error);
} finally {
setIsLoading(false);
}
};
useEffect(() => { useEffect(() => {
const fetchData = async () => { fetchCars();
try { getFeaturedCars().then(setFeaturedCars);
const [allCars, featured] = await Promise.all([
getCars(),
getFeaturedCars()
]);
setCars(allCars);
setFeaturedCars(featured);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, []); }, []);
const handleSearch = async (query: string) => {
await fetchCars(query);
};
return ( return (
<SafeAreaView className={"bg-white h-full"}> <SafeAreaView className={"bg-white h-full"}>
<FlatList <FlatList
@ -65,7 +70,7 @@ export default function Index() {
{/* Search */} {/* Search */}
<View className="px-5 mt-5"> <View className="px-5 mt-5">
<Search /> <Search onSearch={handleSearch} />
</View> </View>
{/* Featured Section */} {/* Featured Section */}
@ -100,6 +105,8 @@ export default function Index() {
contentContainerClassName={"pb-32"} contentContainerClassName={"pb-32"}
columnWrapperClassName={"flex flex-row gap-5 px-5"} columnWrapperClassName={"flex flex-row gap-5 px-5"}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
refreshing={isLoading}
onRefresh={() => fetchCars()}
/> />
{/* Add Car Button */} {/* Add Car Button */}
<TouchableOpacity <TouchableOpacity

View File

@ -1,8 +1,35 @@
import React from 'react'; import React, { useState, useEffect } from 'react';
import { View, TextInput, TouchableOpacity, Image } from 'react-native'; import { View, TextInput, TouchableOpacity, Image } from 'react-native';
import icons from '@/constants/icons'; import icons from '@/constants/icons';
const Search = () => { interface Props {
onSearch: (query: string) => void;
}
export function useDebounce<T>(value: T, delay: number = 500): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(timer);
};
}, [value, delay]);
return debouncedValue;
}
const Search = ({ onSearch }: Props) => {
const [searchQuery, setSearchQuery] = useState('');
const debouncedQuery = useDebounce(searchQuery);
React.useEffect(() => {
onSearch(debouncedQuery);
}, [debouncedQuery]);
return ( return (
<View className="flex-row items-center bg-gray-100 rounded-full px-4 py-2"> <View className="flex-row items-center bg-gray-100 rounded-full px-4 py-2">
<Image source={icons.search} className="w-5 h-5 mr-2" /> <Image source={icons.search} className="w-5 h-5 mr-2" />
@ -10,12 +37,17 @@ const Search = () => {
placeholder="Search cars..." placeholder="Search cars..."
className="flex-1" className="flex-1"
placeholderTextColor="#666" placeholderTextColor="#666"
value={searchQuery}
onChangeText={setSearchQuery}
/> />
<TouchableOpacity> {searchQuery ? (
<Image source={icons.filter} className="w-5 h-5" /> <TouchableOpacity onPress={() => setSearchQuery('')}>
</TouchableOpacity> <Image source={icons.backArrow} className="w-5 h-5" />
</TouchableOpacity>
) : null}
</View> </View>
); );
}; };
export default Search; export default Search;

View File

@ -37,12 +37,21 @@ export async function createCar(carData: Omit<Car, 'id' | 'createdAt'>) {
} }
} }
export async function getCars() { export async function getCars(searchQuery?: string) {
try { try {
const queries = [Query.orderDesc('$createdAt')];
if (searchQuery) {
const searchTerm = searchQuery.toLowerCase();
queries.push(
Query.search('title', searchTerm)
);
}
const response = await databases.listDocuments( const response = await databases.listDocuments(
config.databaseId!, config.databaseId!,
config.carId!, config.carId!,
[Query.orderDesc('$createdAt')] queries
); );
return response.documents; return response.documents;
} catch (error) { } catch (error) {