diff --git a/app/components/header/header.tsx b/app/components/header/header.tsx index e05987d..003a977 100644 --- a/app/components/header/header.tsx +++ b/app/components/header/header.tsx @@ -3,6 +3,7 @@ import { View, Text, TouchableOpacity } from 'react-native'; import { HeaderProps } from './header.props'; import { getStyles } from './header.styles'; import { useAppTheme } from '@theme'; +import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; export const Header: React.FC = ({ title, onBack, rightComponent }) => { const { colors } = useAppTheme(); @@ -13,7 +14,7 @@ export const Header: React.FC = ({ title, onBack, rightComponent }) {onBack && ( - {'<'} + )} diff --git a/app/components/searchBar/searchBar.tsx b/app/components/searchBar/searchBar.tsx index 8b6a603..78b63b2 100644 --- a/app/components/searchBar/searchBar.tsx +++ b/app/components/searchBar/searchBar.tsx @@ -3,6 +3,7 @@ import { View, TextInput, Text } from 'react-native'; import { SearchBarProps } from './searchBar.props'; import { getStyles } from './searchBar.styles'; import { useAppTheme } from '@theme'; +import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; export const SearchBar: React.FC = ({ value, @@ -16,7 +17,11 @@ export const SearchBar: React.FC = ({ return ( - 🔍 + , @@ -37,21 +38,15 @@ const MENU_SECTIONS: MenuSectionData[] = [ { title: 'Account', items: [ - // { - // icon: '📍', - // label: 'My Addresses', - // subLabel: 'Manage delivery addresses', - // tint: '#FDECEA', - // }, { - icon: '💳', + icon: 'wallet-outline', label: 'Wallet', subLabel: 'Cards, UPI & wallets', tint: '#FFF4E5', onPress: navigation => navigation.navigate('WalletScreen'), }, { - icon: '🔔', + icon: 'bell-outline', label: 'Notifications', subLabel: 'Alerts, offers & updates', tint: '#FFF9DB', @@ -62,20 +57,20 @@ const MENU_SECTIONS: MenuSectionData[] = [ title: 'Support & Legal', items: [ { - icon: '❓', + icon: 'help-circle-outline', label: 'Help & Support', subLabel: 'FAQs and contact us', tint: '#EAF4FF', onPress: navigation => navigation.navigate('HelpSupportScreen'), }, { - icon: '📋', + icon: 'file-document-outline', label: 'Terms & Conditions', subLabel: 'Our terms of service', tint: '#F1F0FF', }, { - icon: '🔒', + icon: 'shield-lock-outline', label: 'Privacy Policy', subLabel: 'How we handle your data', tint: '#E9F7EF', @@ -130,7 +125,11 @@ export const AccountScreen: React.FC = () => { {user?.name || 'User'} - 📞 + {user?.phone || '+91 98765 43210'} @@ -182,7 +181,11 @@ export const AccountScreen: React.FC = () => { { backgroundColor: item.tint }, ]} > - {item.icon} + {item.label} diff --git a/app/features/screens/myOrdersScreen/myOrdersScreen.styles.ts b/app/features/screens/myOrdersScreen/myOrdersScreen.styles.ts index 8fddd74..16efca7 100644 --- a/app/features/screens/myOrdersScreen/myOrdersScreen.styles.ts +++ b/app/features/screens/myOrdersScreen/myOrdersScreen.styles.ts @@ -43,4 +43,9 @@ export const getStyles = (colors: any) => StyleSheet.create({ fontSize: typography.fontSize.md, color: colors.textSecondary, }, + loaderContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, }); diff --git a/app/features/screens/myOrdersScreen/myOrdersScreen.tsx b/app/features/screens/myOrdersScreen/myOrdersScreen.tsx index 6c67f5a..201752c 100644 --- a/app/features/screens/myOrdersScreen/myOrdersScreen.tsx +++ b/app/features/screens/myOrdersScreen/myOrdersScreen.tsx @@ -1,8 +1,9 @@ -import React, { useEffect, useState } from 'react'; -import { View, Text, FlatList, TouchableOpacity } from 'react-native'; +import React, { useCallback, useEffect, useState } from 'react'; +import { View, Text, FlatList, TouchableOpacity, ActivityIndicator } from 'react-native'; import { useNavigation, CompositeNavigationProp, + useFocusEffect, } from '@react-navigation/native'; import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs'; import { StackNavigationProp } from '@react-navigation/stack'; @@ -54,14 +55,14 @@ export const MyOrdersScreen: React.FC = () => { const navigation = useNavigation(); const [activeTab, setActiveTab] = useState('All'); const dispatch = useAppDispatch(); - const { orderHistory } = useAppSelector( + const { orderHistory, isLoading } = useAppSelector( (state: RootState) => state.paymentMethods, ); // console.log(orderHistory); - useEffect(() => { + useFocusEffect(useCallback(() => { dispatch(getOrderHistoryThunk()); - }, []); + }, [])); const ONGOING_STATUSES = [ 'PENDING', @@ -103,54 +104,59 @@ export const MyOrdersScreen: React.FC = () => { ))} - item.id} - renderItem={({ item }) => ( - { - if (item?.status === 'OUT_FOR_DELIVERY') { - // navigation.navigate('ProviderDetailsScreen', { - // providerName: item?.merchant?.name || '', - // }); - // } else { - navigation.navigate('LiveTrackingScreen', { - orderId: item?.id || '', + {isLoading ? ( + + + + ) : ( + item.id} + renderItem={({ item }) => ( + { + if (item?.status === 'OUT_FOR_DELIVERY') { + // navigation.navigate('ProviderDetailsScreen', { + // providerName: item?.merchant?.name || '', + // }); + // } else { + navigation.navigate('LiveTrackingScreen', { + orderId: item?.id || '', + }); + } + }} + onDetails={() => { + // if ( + // item?.status === 'PENDING' || + // item?.status === 'CONFIRMED' || + // item?.status === 'PREPARING' || + // item?.status === 'READY_FOR_PICKUP' || + // item?.status === 'OUT_FOR_DELIVERY' + // ) { + navigation.navigate('OrderDetailsScreen', { + orderId: item.id, }); - } - }} - onDetails={() => { - // if ( - // item?.status === 'PENDING' || - // item?.status === 'CONFIRMED' || - // item?.status === 'PREPARING' || - // item?.status === 'READY_FOR_PICKUP' || - // item?.status === 'OUT_FOR_DELIVERY' - // ) { - navigation.navigate('OrderDetailsScreen', { - orderId: item.id, - }); - // } else { - // navigation.navigate('OrderDeliveredScreen', { - // orderId: item.id, - // }); - // } - }} - /> - )} - contentContainerStyle={styles.list} - ListEmptyComponent={ - - No orders found - - } - /> + // } else { + // navigation.navigate('OrderDeliveredScreen', { + // orderId: item.id, + // }); + // } + }} + /> + )} + contentContainerStyle={styles.list} + ListEmptyComponent={ + + No orders found + + } + />)} ); }; diff --git a/app/features/screens/offersScreen/offersScreen.tsx b/app/features/screens/offersScreen/offersScreen.tsx index 2c4dda3..825b7c9 100644 --- a/app/features/screens/offersScreen/offersScreen.tsx +++ b/app/features/screens/offersScreen/offersScreen.tsx @@ -14,6 +14,7 @@ import { Header } from '@components'; import { useAppTheme } from '@theme'; import { useAppDispatch, useAppSelector, getAllOffersThunk } from '@store'; import { Promotion, PromotionType } from '@interfaces'; +import Clipboard from '@react-native-clipboard/clipboard'; const getPromoVisuals = (type: PromotionType) => { switch (type) { @@ -69,16 +70,18 @@ export const OffersScreen: React.FC = () => { }, [dispatch]), ); - // const handleCopy = (item: Promotion) => { - // setCopiedId(item.id); - // const textToCopy = item.badgeText || item.title; - // if (Platform.OS === 'android') { - // ToastAndroid.show(`Copied "${textToCopy}"`, ToastAndroid.SHORT); - // } - // setTimeout(() => { - // setCopiedId(prev => (prev === item.id ? null : prev)); - // }, 2000); - // }; + const handleCopy = (item: Promotion) => { + + Clipboard.setString(item.badgeText); + setCopiedId(item.id); + // const textToCopy = item.badgeText || item.title; + // if (Platform.OS === 'android') { + // ToastAndroid.show(`Copied "${textToCopy}"`, ToastAndroid.SHORT); + // } + setTimeout(() => { + setCopiedId(prev => (prev === item.id ? null : prev)); + }, 2000); + }; const renderOfferCard = ({ item }: { item: Promotion }) => { const visuals = getPromoVisuals(item.promotionType); @@ -119,8 +122,8 @@ export const OffersScreen: React.FC = () => { handleCopy(item)} - onPress={() => { }} + onPress={() => handleCopy(item)} + // onPress={() => { }} activeOpacity={0.8} > diff --git a/app/features/screens/providerDetailsScreen/providerDetailsScreen.tsx b/app/features/screens/providerDetailsScreen/providerDetailsScreen.tsx index d6097ba..55bcdb8 100644 --- a/app/features/screens/providerDetailsScreen/providerDetailsScreen.tsx +++ b/app/features/screens/providerDetailsScreen/providerDetailsScreen.tsx @@ -22,6 +22,7 @@ import { useAppDispatch, useAppSelector } from '@store'; import { getProductDetailsThunk } from './thunk'; import { getDiscountPercentage, formatPrice } from '@components'; import { getFullUrl } from '@utils'; +import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; type ProviderDetailsNavProp = StackNavigationProp< AppStackParamList, @@ -101,8 +102,7 @@ export const ProviderDetailsScreen: React.FC = () => { const handleIncrement = () => { if (!product) return; const newQty = localQty + 1; - setLocalQty(newQty); - dispatch(updateCartItemThunk({ productId: product.id, quantity: newQty })); + dispatch(updateCartItemThunk({ productId: product.id, quantity: newQty })).unwrap().then(() => setLocalQty(newQty)); }; const handleDecrement = () => { @@ -375,7 +375,7 @@ export const ProviderDetailsScreen: React.FC = () => { activeOpacity={0.8} onPress={() => navigation.goBack()} > - + { {localQty} setLocalQty(q => q + 1)} + onPress={handleAddToCart} activeOpacity={0.7} > + diff --git a/app/features/screens/searchScreen/searchScreen.tsx b/app/features/screens/searchScreen/searchScreen.tsx index 67e1ff8..8896c42 100644 --- a/app/features/screens/searchScreen/searchScreen.tsx +++ b/app/features/screens/searchScreen/searchScreen.tsx @@ -23,6 +23,7 @@ import { MainTabParamList } from '../../../navigation/mainTabNavigator'; import { useAppDispatch, useAppSelector } from '@store'; import { getProductsByCategoryThunk } from './thunk'; import { Products } from '@interfaces'; +import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; // ─── Types ─────────────────────────────────────────────────────────────────── @@ -114,7 +115,7 @@ export const SearchScreen: React.FC = () => { searchQuery.trim().length === 0 ? true : p.name.toLowerCase().includes(searchQuery.toLowerCase()) || - (p.brand ?? '').toLowerCase().includes(searchQuery.toLowerCase()), + (p.brand ?? '').toLowerCase().includes(searchQuery.toLowerCase()), ); // Category chips: prepend "All" @@ -207,7 +208,7 @@ export const SearchScreen: React.FC = () => { activeOpacity={0.7} onPress={() => navigation.goBack()} > - + {headerCategoryName} diff --git a/package.json b/package.json index 28b1ee9..268f99b 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@react-native-async-storage/async-storage": "^3.1.1", + "@react-native-clipboard/clipboard": "^1.16.3", "@react-native-community/checkbox": "^0.5.20", "@react-native/new-app-screen": "0.86.0", "@react-navigation/bottom-tabs": "^7.18.3", diff --git a/yarn.lock b/yarn.lock index a2ced0c..8505632 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1386,6 +1386,11 @@ dependencies: idb "8.0.3" +"@react-native-clipboard/clipboard@^1.16.3": + version "1.16.3" + resolved "https://registry.yarnpkg.com/@react-native-clipboard/clipboard/-/clipboard-1.16.3.tgz#7807a90fd9984bf4d3a96faf2eee20457984a9bd" + integrity sha512-cMIcvoZKIrShzJHEaHbTAp458R9WOv0fB6UyC7Ek4Qk561Ow/DrzmmJmH/rAZg21Z6ixJ4YSdFDC14crqIBmCQ== + "@react-native-community/checkbox@^0.5.20": version "0.5.20" resolved "https://registry.yarnpkg.com/@react-native-community/checkbox/-/checkbox-0.5.20.tgz#7b8004a80a90988d5dff208693524f069270b849"