freshyo/apps/user-ui/app/(drawer)/(tabs)/order-again/index.tsx
2026-08-15 10:34:28 +05:30

172 lines
5 KiB
TypeScript

import React, { useState } from "react";
import { View, Dimensions, ScrollView } from "react-native";
import { useRouter } from "expo-router";
import {
tw,
useManualRefresh,
useMarkDataFetchers,
AppContainer,
MyText,
MyTouchableOpacity,
} from "common-ui";
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import ProductCard from "@/components/ProductCard";
import { trpc } from "@/src/trpc-client";
import FloatingCartBar from "@/components/floating-cart-bar";
import TabLayoutWrapper from "@/components/TabLayoutWrapper";
const { width: screenWidth } = Dimensions.get("window");
// Same 3-column hero card sizing used on the home page.
const heroItemWidth = (screenWidth - 72) / 3;
const SHOW_MORE_STEP = 6;
interface OffersSectionProps {
title: string;
subtitle: string;
products: any[];
expanded: boolean;
onExpand: () => void;
onProductPress: (id: number) => void;
}
// Grid section (home page style): shows the first SHOW_MORE_STEP products
// with a "Show More" button to reveal the rest.
const OffersSection = ({
title,
subtitle,
products,
expanded,
onExpand,
onProductPress,
}: OffersSectionProps) => {
const visible = expanded ? products : products.slice(0, SHOW_MORE_STEP);
const hasMore = products.length > SHOW_MORE_STEP && !expanded;
return (
<View style={tw`pt-4`}>
<View style={tw`mb-2 px-4`}>
<MyText style={tw`text-2xl font-extrabold text-gray-900 tracking-tight`}>
{title}
</MyText>
<MyText style={tw`text-sm text-gray-500 font-medium`}>
{subtitle}
</MyText>
</View>
{products.length === 0 ? (
<View style={tw`items-center justify-center py-10`}>
<MaterialIcons name="local-offer" size={28} color="#9CA3AF" />
<MyText style={tw`text-gray-500 mt-2`}>
No {title.toLowerCase()} available right now
</MyText>
</View>
) : (
<>
<View style={tw`flex-row flex-wrap gap-5 px-4`}>
{visible.map((item: any) => (
<View key={item.id} style={tw`mb-3`}>
<ProductCard
item={item}
itemWidth={heroItemWidth}
onPress={() => onProductPress(item.id)}
showDeliveryInfo={false}
useAddToCartDialog={true}
miniView={true}
variant="hero"
/>
</View>
))}
</View>
{hasMore && (
<MyTouchableOpacity
style={tw`self-center mt-1 mb-2 px-5 py-2.5 rounded-full bg-brand500 shadow-sm`}
activeOpacity={0.85}
onPress={onExpand}
>
<MyText style={tw`text-white text-sm font-semibold`}>Show More</MyText>
</MyTouchableOpacity>
)}
</>
)}
</View>
);
};
export default function Offers() {
const router = useRouter();
const [expandedOffers, setExpandedOffers] = useState(false);
const [expandedCombos, setExpandedCombos] = useState(false);
const { data, isLoading, error, refetch } =
trpc.user.product.getOffersPage.useQuery();
const combos = data?.combos || [];
const offers = data?.offers || [];
useManualRefresh(() => {
refetch();
});
useMarkDataFetchers(() => {
refetch();
});
if (isLoading) {
return (
<AppContainer>
<View style={tw`flex-1 justify-center items-center bg-gray-50`}>
<MaterialIcons name="local-offer" size={48} color="#3B82F6" />
<MyText style={tw`text-gray-500 font-medium mt-4`}>
Loading offers...
</MyText>
</View>
</AppContainer>
);
}
if (error) {
return (
<AppContainer>
<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 offers
</MyText>
</View>
</AppContainer>
);
}
const handleProductPress = (id: number) => {
router.push(`/(drawer)/(tabs)/order-again/product-detail/${id}`);
};
return (
<TabLayoutWrapper>
<ScrollView style={tw`flex-1`} contentContainerStyle={tw`pb-20`}>
<OffersSection
title="Offers"
subtitle="Great prices on select items"
products={offers}
expanded={expandedOffers}
onExpand={() => setExpandedOffers(true)}
onProductPress={handleProductPress}
/>
<OffersSection
title="Combos"
subtitle="Bundle your favorites and save"
products={combos}
expanded={expandedCombos}
onExpand={() => setExpandedCombos(true)}
onProductPress={handleProductPress}
/>
</ScrollView>
<View style={tw`absolute bottom-2 left-4 right-4`}>
<FloatingCartBar />
</View>
</TabLayoutWrapper>
);
}