From 8e2e863b84633b6852c2af5d577b9f16475b9851 Mon Sep 17 00:00:00 2001 From: shafi54 <108669266+shafi-aviz@users.noreply.github.com> Date: Sat, 8 Aug 2026 21:49:42 +0530 Subject: [PATCH] enh --- .../app/(drawer)/(tabs)/home/index.tsx | 213 +++++------------- 1 file changed, 58 insertions(+), 155 deletions(-) diff --git a/apps/user-ui/app/(drawer)/(tabs)/home/index.tsx b/apps/user-ui/app/(drawer)/(tabs)/home/index.tsx index 39fe454..65c7a83 100755 --- a/apps/user-ui/app/(drawer)/(tabs)/home/index.tsx +++ b/apps/user-ui/app/(drawer)/(tabs)/home/index.tsx @@ -1,5 +1,5 @@ -import React, { useState, useCallback, useMemo, memo, useRef } from "react"; -import { View, Dimensions, Image, RefreshControl, ScrollView } from "react-native"; +import React, { useState, useCallback, useMemo, memo } from "react"; +import { View, Dimensions, Image, RefreshControl } from "react-native"; import { TabView, TabBar } from "react-native-tab-view"; import { LinearGradient } from "expo-linear-gradient"; import { useRouter } from "expo-router"; @@ -39,7 +39,7 @@ const gridItemWidth = (screenWidth - 48) / 2; // Hero product card geometry (used to size the tab scene heights) const heroCardImageHeight = heroItemWidth * 0.82; -const heroCardTextBlock = 86; +const heroCardTextBlock = 92; const heroCardHeight = heroCardImageHeight + heroCardTextBlock; const heroRowHeight = heroCardHeight + 12; // + mb-3 const TAG_GRID_COLUMNS = 3; @@ -60,9 +60,9 @@ const formatTimeRange = (deliveryTime: string) => { const staticStyles = { flatListContent: { gap: 16 }, - columnWrapper: { gap: 16, paddingHorizontal: 16 }, + columnWrapper: { justifyContent: 'space-between', paddingHorizontal: 16 }, slotsListContent: { paddingBottom: 24 }, -}; +} as const; const TAG_COLORS = [ { pageBg: '#FFF8F9', bg: '#FFF1F2', border: '#FECDD3', text: '#9F1239', dot: '#E11D48' }, // rose @@ -195,45 +195,6 @@ const SlotCard = memo(({ slot }: SlotCardProps) => { ); }); -interface ExploreTabProps { - tag: any; - isSelected: boolean; - onPress: () => void; -} - -const ExploreTab = memo(({ tag, isSelected, onPress }: ExploreTabProps) => { - return ( - - - - {tag.tagName} - - - - - ); -}); - interface TagTabViewProps { dashboardTags: any[]; activeTagId: number | null; @@ -261,17 +222,18 @@ const TagTabView = memo(({ return idx < 0 ? 0 : idx; }, [dashboardTags, activeTagId]); - // Height: fit the max visible product rows across all tags (default 6 per tag). + // Height: fit the active tag's visible product rows (default 6 per tag), + // plus room for the "Show More" button when it has more products. + const activeTagKey = routes[index]?.key; const sceneHeight = useMemo(() => { - let maxRows = 1; - for (const tag of dashboardTags) { - const count = (productsByTagId[tag.id] || []).length; - const visible = expandedByTagId[tag.id] ? count : Math.min(count, 6); - const rows = Math.max(1, Math.ceil(visible / TAG_GRID_COLUMNS)); - maxRows = Math.max(maxRows, rows); - } - return maxRows * heroRowHeight + 16; - }, [dashboardTags, productsByTagId, expandedByTagId]); + const tagId = Number(activeTagKey); + const count = (productsByTagId[tagId]?.length) || 0; + const expanded = expandedByTagId[tagId]; + const visible = expanded ? count : Math.min(count, 6); + const rows = Math.max(1, Math.ceil(visible / TAG_GRID_COLUMNS)); + const showMore = count > 6 && !expanded; + return rows * heroRowHeight + 24 + (showMore ? 52 : 0); + }, [activeTagKey, productsByTagId, expandedByTagId]); const renderTabBar = useCallback((props: any) => ( void; -} - -const StickyTabsRow = memo(({ dashboardTags, activeTagId, onSelectTag }: StickyTabsRowProps) => { - const scrollRef = useRef(null); - - const handleSelect = (id: number) => { - onSelectTag(id); - const idx = dashboardTags.findIndex((tag) => tag.id === id); - if (idx >= 0) { - scrollRef.current?.scrollTo({ x: idx * 96, animated: true }); - } - }; - - return ( - - {dashboardTags.map((tag) => ( - handleSelect(tag.id)} /> - ))} - - ); -}); - interface ExploreProductItemProps { item: any; onPress: (id: number) => void; @@ -408,14 +339,17 @@ const ProductItem = memo(({ item, onPress }: ProductItemProps) => { const handlePress = useCallback(() => onPress(item.id), [item.id, onPress]); return ( - + + + ); }); @@ -429,7 +363,6 @@ interface ListHeaderProps { activeTagId: number | null; productsByTagId: Record; onSelectTag: (id: number) => void; - onTabsSectionLayout: (layout: { y: number; height: number }) => void; } const ListHeader = memo(({ @@ -442,7 +375,6 @@ const ListHeader = memo(({ activeTagId, productsByTagId, onSelectTag, - onTabsSectionLayout, }: ListHeaderProps) => { const handleLayout = useCallback((event: any) => { const { y, height } = event.nativeEvent.layout; @@ -472,10 +404,6 @@ const ListHeader = memo(({ {dashboardTags.length > 0 && ( { - const { y, height } = event.nativeEvent.layout; - onTabsSectionLayout({ y, height }); - }} style={[ tw`mx-4 mb-2 rounded-[28px] px-3 pt-3 pb-[30px]`, { backgroundColor: theme.colors.brand25 }, @@ -549,8 +477,8 @@ const ListHeader = memo(({ )} - - + + @@ -572,11 +500,8 @@ export default function Dashboard() { const [isLoadingDialogOpen, setIsLoadingDialogOpen] = useState(false); const [gradientHeight, setGradientHeight] = useState(0); const [displayedProducts, setDisplayedProducts] = useState([]); + const [visibleCount, setVisibleCount] = useState(21); const [hasMore, setHasMore] = useState(true); - const [isLoadingMore, setIsLoadingMore] = useState(false); - const [searchBarHeight, setSearchBarHeight] = useState(0); - const [tabsSectionLayout, setTabsSectionLayout] = useState({ y: 0, height: 0 }); - const [showStickyTabs, setShowStickyTabs] = useState(false); const { getQuickestSlot } = useProductSlotIdentifier(); const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap); const refetchProducts = useCentralProductStore((state) => state.refetchProducts); @@ -608,7 +533,7 @@ export default function Dashboard() { return } - const initialBatch = products + const allSorted = products .filter(p => typeof p.id === "number") .sort((a, b) => { const slotA = getQuickestSlot(a.id) @@ -622,10 +547,19 @@ export default function Dashboard() { return 0 }) - setDisplayedProducts(initialBatch) - setHasMore(products.length > 10) + setDisplayedProducts(allSorted) + setVisibleCount(21) + setHasMore(allSorted.length > 21) }, [productsData, productSlotsMap]); + const handleShowMore = useCallback(() => { + setVisibleCount((prev) => { + const next = prev + 21; + setHasMore(next < displayedProducts.length); + return next; + }); + }, [displayedProducts.length]); + const sortedSlots = useMemo(() => { if (!slotsData?.slots) return []; const now = dayjs(); @@ -716,19 +650,6 @@ export default function Dashboard() { router.push("/(drawer)/(tabs)/home/search-results"); }, [router]); - const handleTabsSectionLayout = useCallback((layout: { y: number; height: number }) => { - setTabsSectionLayout(layout); - }, []); - - const handleListScroll = useCallback((event: any) => { - const scrollY = event.nativeEvent.contentOffset.y; - const stickyStart = tabsSectionLayout.y; - const stickyEnd = tabsSectionLayout.y + tabsSectionLayout.height - 56; - const shouldShowStickyTabs = tabsSectionLayout.height > 0 && scrollY > stickyStart && scrollY < stickyEnd; - - setShowStickyTabs((current) => current === shouldShowStickyTabs ? current : shouldShowStickyTabs); - }, [tabsSectionLayout]); - const renderProductItem = useCallback(({ item }: { item: any }) => ( // @@ -745,9 +666,8 @@ export default function Dashboard() { activeTagId={activeTagId} productsByTagId={productsByTagId} onSelectTag={setSelectedTagId} - onTabsSectionLayout={handleTabsSectionLayout} /> - ), [gradientHeight, handleGradientLayout, storesData, sortedSlots, handleProductPress, dashboardTags, activeTagId, productsByTagId, handleTabsSectionLayout]); + ), [gradientHeight, handleGradientLayout, storesData, sortedSlots, handleProductPress, dashboardTags, activeTagId, productsByTagId]); const pageTint = activeTagId == null ? '#FFFFFF' : getTagColor(activeTagId).pageBg; const pageTintStyle = useMemo(() => [ @@ -791,7 +711,6 @@ export default function Dashboard() { setSearchBarHeight(event.nativeEvent.layout.height)} > item.id.toString()} - numColumns={2} + numColumns={3} style={{ backgroundColor: '#FFFFFF' }} - onScroll={handleListScroll} - scrollEventThrottle={16} contentContainerStyle={listContentContainerStyle} columnWrapperStyle={staticStyles.columnWrapper} renderItem={renderProductItem} ListHeaderComponent={listHeader} + ListFooterComponent={ + hasMore ? ( + + + Show More + + + ) : null + } refreshControl={ - {showStickyTabs && dashboardTags.length > 0 && ( - - - - - - )} -