This commit is contained in:
shafi54 2026-01-24 15:39:42 +05:30
parent 1f801f2146
commit ccde89b5c8
2 changed files with 198 additions and 86 deletions

View file

@ -96,6 +96,10 @@ export default function Dashboard() {
const [gradientHeight, setGradientHeight] = useState(0); const [gradientHeight, setGradientHeight] = useState(0);
const [stickyBarLayout, setStickyBarLayout] = useState({ y: 0, height: 0 }); const [stickyBarLayout, setStickyBarLayout] = useState({ y: 0, height: 0 });
const [whiteSectionLayout, setWhiteSectionLayout] = useState({ y: 0 }); const [whiteSectionLayout, setWhiteSectionLayout] = useState({ y: 0 });
const [displayedProducts, setDisplayedProducts] = useState<any[]>([]);
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);
const [isLoadingMore, setIsLoadingMore] = useState(false);
const { backgroundColor } = useStatusBarStore(); const { backgroundColor } = useStatusBarStore();
const { const {
@ -121,6 +125,47 @@ export default function Dashboard() {
const defaultAddress = defaultAddressResponse?.data; const defaultAddress = defaultAddressResponse?.data;
const { getQuickestSlot } = useProductSlotIdentifier(); const { getQuickestSlot } = useProductSlotIdentifier();
// Function to load more products
const loadMoreProducts = () => {
if (!hasMore || isLoadingMore) return;
setIsLoadingMore(true);
// Simulate loading more products by taking the next batch
// In a real app, you would make an API call with pagination params
setTimeout(() => {
const batchSize = 10;
const startIndex = page * batchSize;
const endIndex = startIndex + batchSize;
// Get the next batch of products
const nextBatch = products.slice(startIndex, endIndex);
if (nextBatch.length > 0) {
setDisplayedProducts(prev => [...prev, ...nextBatch]);
setPage(prev => prev + 1);
setHasMore(endIndex < products.length);
} else {
setHasMore(false);
}
setIsLoadingMore(false);
}, 500); // Simulate network delay
};
// Initialize with the first batch of products
React.useEffect(() => {
if (products.length > 0) {
const initialBatch = products.slice(0, 10); // First 10 products
setDisplayedProducts(initialBatch);
setHasMore(products.length > 10);
setPage(1);
} else {
setDisplayedProducts([]);
setHasMore(false);
}
}, [products]);
// Extract popular items IDs as an array to preserve order // Extract popular items IDs as an array to preserve order
const popularItemIds = (() => { const popularItemIds = (() => {
const popularItems = essentialConsts?.popularItems; const popularItems = essentialConsts?.popularItems;
@ -202,7 +247,20 @@ export default function Dashboard() {
<ScrollView <ScrollView
style={[tw`flex-1 bg-white`, { position: 'relative' }]} style={[tw`flex-1 bg-white`, { position: 'relative' }]}
stickyHeaderIndices={[2]} stickyHeaderIndices={[2]}
onScroll={handleScroll} onScroll={(e) => {
handleScroll(e);
// Check if we're near the end of the scroll for vertical loading
const { layoutMeasurement, contentOffset, contentSize } = e.nativeEvent;
const paddingToBottom = 40;
if (layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom) {
// Load more products when reaching near the end
if (!isLoadingMore && hasMore) {
loadMoreProducts();
}
}
}}
scrollEventThrottle={16} scrollEventThrottle={16}
> >
<LinearGradient <LinearGradient
@ -363,7 +421,7 @@ export default function Dashboard() {
<MyText <MyText
style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`} style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`}
> >
Delivery Slots Upcoming Delivery Slots
</MyText> </MyText>
<MyText style={tw`text-sm text-gray-500 font-medium mt-1`}> <MyText style={tw`text-sm text-gray-500 font-medium mt-1`}>
Plan your fresh deliveries ahead Plan your fresh deliveries ahead
@ -516,6 +574,49 @@ export default function Dashboard() {
</ScrollView> </ScrollView>
</View> </View>
)} )}
{/* All Products Section - Vertical Infinite Scroll */}
<View style={tw`mt-2 mb-4`}>
<View style={tw`flex-row items-center justify-between px-1 mb-6`}>
<View>
<MyText
style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`}
>
All Available Products
</MyText>
<MyText style={tw`text-sm text-gray-500 font-medium mt-1`}>
Browse our complete selection
</MyText>
</View>
</View>
{/* Product Grid */}
<View style={tw`flex-row flex-wrap`}>
{displayedProducts.map((item, index: number) => (
<ProductCard
item={item}
itemWidth={(screenWidth * 0.9) / 2} // Half of screen width minus padding
onPress={() =>
router.push(
`/(drawer)/(tabs)/home/product-detail/${item.id}`
)
}
showDeliveryInfo={true}
miniView={false}
nullIfNotAvailable={true}
containerComp={({children}) => <View key={item.id} style={tw`w-1/2 pr-2 pb-4`}>{children}</View>}
/>
))}
</View>
{isLoadingMore && (
<View style={tw`items-center py-4`}>
<MyText>Loading more...</MyText>
</View>
)}
</View>
</View> </View>
<LoadingDialog open={isLoadingDialogOpen} message="Adding to cart..." /> <LoadingDialog open={isLoadingDialogOpen} message="Adding to cart..." />

View file

@ -21,6 +21,8 @@ interface ProductCardProps {
onPress?: () => void; onPress?: () => void;
showDeliveryInfo?: boolean; showDeliveryInfo?: boolean;
miniView?: boolean; miniView?: boolean;
nullIfNotAvailable?: boolean;
containerComp?: React.ComponentType<any> | React.JSXElementConstructor<any>;
} }
const formatQuantity = (quantity: number, unit: string): { value: string; display: string } => { const formatQuantity = (quantity: number, unit: string): { value: string; display: string } => {
@ -36,6 +38,8 @@ const ProductCard: React.FC<ProductCardProps> = ({
onPress, onPress,
showDeliveryInfo = true, showDeliveryInfo = true,
miniView = false, miniView = false,
nullIfNotAvailable = false,
containerComp: ContainerComp = React.Fragment,
}) => { }) => {
const { data: cartData } = useGetCart(); const { data: cartData } = useGetCart();
const { getQuickestSlot } = useProductSlotIdentifier(); const { getQuickestSlot } = useProductSlotIdentifier();
@ -63,6 +67,11 @@ const ProductCard: React.FC<ProductCardProps> = ({
const slotId = getQuickestSlot(item.id); const slotId = getQuickestSlot(item.id);
const displayIsOutOfStock = item.isOutOfStock || !slotId; const displayIsOutOfStock = item.isOutOfStock || !slotId;
// Return null if nullIfNotAvailable is true and the product is out of stock
if (nullIfNotAvailable && displayIsOutOfStock) {
return null;
}
const handleQuantityChange = (newQuantity: number) => { const handleQuantityChange = (newQuantity: number) => {
if (newQuantity === 0 && cartItem) { if (newQuantity === 0 && cartItem) {
removeFromCart.mutate({ itemId: cartItem.id }); removeFromCart.mutate({ itemId: cartItem.id });
@ -79,9 +88,10 @@ const ProductCard: React.FC<ProductCardProps> = ({
}; };
return ( return (
<ContainerComp>
<MyTouchableOpacity <MyTouchableOpacity
style={[ style={[
tw`bg-white rounded-2xl overflow-hidden border border-gray-200`, tw`bg-white rounded-2xl overflow-hidden border border-gray-200 pb-2`,
{ width: itemWidth }, { width: itemWidth },
]} ]}
onPress={onPress || (() => {/* TODO: Navigate to product detail */})} onPress={onPress || (() => {/* TODO: Navigate to product detail */})}
@ -168,6 +178,7 @@ const ProductCard: React.FC<ProductCardProps> = ({
)} )}
</View> </View>
</MyTouchableOpacity> </MyTouchableOpacity>
</ContainerComp>
); );
}; };