import React, { useState, useCallback } from 'react'; import { View, ScrollView, Alert } from 'react-native'; import { AppContainer, MyText, tw, useMarkDataFetchers, MyTouchableOpacity, MyTextInput } from 'common-ui'; import { useLocalSearchParams, useRouter } from 'expo-router'; import { useFocusEffect } from '@react-navigation/native'; import { useAppStore } from '@/src/store/appStore'; import { trpc } from '@/src/trpc-client'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import dayjs from 'dayjs'; interface CouponCardProps { coupon: { id: number; code: string; discountType: 'percentage' | 'flat'; discountValue: number; maxValue?: number; minOrder?: number; description: string; validTill?: string | Date; usageCount: number; maxLimitForUser?: number; isExpired: boolean; isUsedUp: boolean; }; } function CouponCard({ coupon }: CouponCardProps) { const getStatusColor = () => { if (coupon.isExpired) return 'text-red-500'; if (coupon.isUsedUp) return 'text-orange-500'; return 'text-green-600'; }; const getStatusText = () => { if (coupon.isExpired) return 'Expired'; if (coupon.isUsedUp) return 'Used'; return 'Available'; }; const formatDate = (date?: string | Date) => { if (!date) return 'No expiry'; return dayjs(date).format('DD MMM YYYY'); }; return ( {coupon.code} {coupon.description} {getStatusText()} {coupon.maxLimitForUser && ( Used: {coupon.usageCount}/{coupon.maxLimitForUser} )} Valid till: {formatDate(coupon.validTill)} {coupon.isExpired || coupon.isUsedUp ? 'Unavailable' : 'Apply'} ); } function CouponSection({ title, coupons, emptyMessage }: { title: string; coupons: CouponCardProps['coupon'][]; emptyMessage: string; }) { return ( {title} {coupons.length === 0 ? ( {emptyMessage} ) : ( coupons.map(coupon => ( )) )} ); } export default function Coupons() { const router = useRouter(); const { from } = useLocalSearchParams<{ from?: string }>(); const setHideTabsNavKey = useAppStore((state) => state.setHideTabsNavKey); // Hide bottom tab bar when opened from the cart page useFocusEffect( useCallback(() => { if (from !== 'cart') return; setHideTabsNavKey('coupons-from-cart', true); return () => setHideTabsNavKey('coupons-from-cart', false); }, [from, setHideTabsNavKey]) ); const { data, isLoading, error, refetch } = trpc.user.coupon.getMyCoupons.useQuery(); const [couponCode, setCouponCode] = useState(''); const redeemCouponMutation = trpc.user.coupon.redeemReservedCoupon.useMutation({ onSuccess: () => { setCouponCode(''); refetch(); Alert.alert('Success', 'Coupon added successfully!'); }, onError: (error: any) => { Alert.alert('Error', error.message || 'Failed to add coupon. Please check the code and try again.'); } }); useMarkDataFetchers(() => { refetch(); }); if (isLoading) { return ( Loading coupons... ); } if (error) { return ( Failed to load coupons. Please try again. ); } const personalCoupons = data?.data?.personal || []; const generalCoupons = data?.data?.general || []; return ( {from === 'cart' && ( router.navigate('/(drawer)/(tabs)/home/cart')} style={tw`p-2 -ml-2 mr-1 mb-2 self-start`} activeOpacity={0.7} > )} Add a Coupon { if (couponCode.trim().length >= 4) { redeemCouponMutation.mutate({ secretCode: couponCode.trim().toUpperCase() }); } }} > {redeemCouponMutation.isPending ? 'Adding...' : 'Add Coupon'} ); }