freshyo/apps/user-ui/app/(drawer)/(tabs)/home/search-results/index.tsx
2026-01-24 00:13:15 +05:30

176 lines
No EOL
4.9 KiB
TypeScript

import React, { useState, useRef, useEffect } from "react";
import {
View,
Dimensions,
Image,
Alert,
Platform,
} from "react-native";
import { useRouter, useLocalSearchParams } from "expo-router";
import {
theme,
tw,
useManualRefresh,
useMarkDataFetchers,
LoadingDialog,
AppContainer,
MyFlatList,
MyText,
MyTextInput,
MyTouchableOpacity,
SearchBar } from "common-ui";
import dayjs from "dayjs";
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import { trpc } from "@/src/trpc-client";
import { useGetCart, useAddToCart } from '@/hooks/cart-query-hooks';
import ProductCard from "@/components/ProductCard";
import FloatingCartBar from "@/components/floating-cart-bar";
const { width: screenWidth } = Dimensions.get("window");
const itemWidth = (screenWidth - 48) / 2; // 48 = padding horizontal (16*2) + gap (16)
export default function SearchResults() {
const router = useRouter();
const { q } = useLocalSearchParams();
const query = (q as string) || "";
const [inputQuery, setInputQuery] = useState(query);
const [searchQuery, setSearchQuery] = useState(query);
const [isLoadingDialogOpen, setIsLoadingDialogOpen] = useState(false);
const searchInputRef = useRef<any>(null);
useEffect(() => {
// Auto-focus search bar on mount
setTimeout(() => {
searchInputRef.current?.focus();
}, 100);
}, []);
const {
data: productsData,
isLoading,
error,
refetch,
} = trpc.common.product.getAllProductsSummary.useQuery({
searchQuery: searchQuery || undefined,
});
const { data: cartData, refetch: refetchCart } = useGetCart();
const products = productsData?.products || [];
const addToCart = useAddToCart({ showSuccessAlert: false, showErrorAlert: false, refetchCart: true });
useManualRefresh(() => {
refetch();
});
useMarkDataFetchers(() => {
refetch();
});
const handleAddToCart = (productId: number) => {
setIsLoadingDialogOpen(true);
addToCart.mutate(
{ productId, quantity: 1 },
{
onSuccess: () => {
Alert.alert("Success", "Item added to cart!");
refetchCart();
},
onError: (error: any) => {
Alert.alert("Error", error.message || "Failed to add item to cart");
},
onSettled: () => {
setIsLoadingDialogOpen(false);
},
}
);
};
const handleBuyNow = (productId: number) => {
setIsLoadingDialogOpen(true);
addToCart.mutate(
{ productId, quantity: 1 },
{
onSuccess: () => {
router.push(`/(drawer)/(tabs)/home/cart?select=${productId}`);
},
onError: (error: any) => {
Alert.alert("Error", error.message || "Failed to add item to cart");
},
onSettled: () => {
setIsLoadingDialogOpen(false);
},
}
);
};
const handleSearch = () => {
setSearchQuery(inputQuery);
};
if (isLoading) {
return (
<View style={tw`flex-1 justify-center items-center bg-gray-50`}>
<MyText style={tw`text-gray-500 font-medium`}>Loading products...</MyText>
</View>
);
}
if (error) {
return (
<View style={tw`flex-1 justify-center items-center bg-gray-50`}>
<MaterialIcons name="error-outline" size={48} color="#EF4444" />
<MyText style={tw`text-gray-900 text-lg font-bold mt-4`}>Oops!</MyText>
<MyText style={tw`text-gray-500 mt-2`}>Failed to load products</MyText>
</View>
);
}
return (
<View style={tw`flex-1 bg-gray-50`}>
<MyFlatList
data={products}
numColumns={2}
renderItem={({ item }) => (
<ProductCard
item={item}
handleAddToCart={handleAddToCart}
handleBuyNow={handleBuyNow}
itemWidth={itemWidth}
onPress={() => router.push(`/(drawer)/(tabs)/home/product-detail/${item.id}`)}
showDeliveryInfo={false}
iconType="flash"
/>
)}
keyExtractor={(item, index) => index.toString()}
columnWrapperStyle={{ gap: 16, justifyContent: 'center' }}
contentContainerStyle={[tw`pb-24`, { gap: 16 }]}
ListHeaderComponent={
<View style={tw`pt-4 pb-2 px-4`}>
{/* Search Bar */}
<SearchBar
ref={searchInputRef}
value={inputQuery}
onChangeText={setInputQuery}
onSubmitEditing={handleSearch}
returnKeyType="search"
/>
{/* Section Title */}
<View style={tw`flex-row justify-between items-center mb-2`}>
<MyText style={tw`text-lg font-bold text-gray-900`}>
{searchQuery ? `Search Results for "${searchQuery}"` : 'All Products'}
</MyText>
</View>
</View>
}
/>
<LoadingDialog open={isLoadingDialogOpen} message="Adding to cart..." />
<View style={tw`absolute bottom-2 left-4 right-4`}>
<FloatingCartBar />
</View>
</View>
);
}