225 lines
6.7 KiB
TypeScript
225 lines
6.7 KiB
TypeScript
import React, { useState, useCallback } from 'react';
|
||
import {
|
||
View,
|
||
Text,
|
||
FlatList,
|
||
TouchableOpacity,
|
||
StatusBar,
|
||
ToastAndroid,
|
||
Platform,
|
||
} from 'react-native';
|
||
import { useFocusEffect } from '@react-navigation/native';
|
||
import { getStyles } from './offersScreen.styles';
|
||
import { Header } from '@components';
|
||
import { useAppTheme } from '@theme';
|
||
import { useAppDispatch, useAppSelector, getAllOffersThunk } from '@store';
|
||
import { Promotion, PromotionType } from '@interfaces';
|
||
|
||
const getPromoVisuals = (type: PromotionType) => {
|
||
switch (type) {
|
||
case 'FREE_DELIVERY':
|
||
return {
|
||
emoji: '🛵',
|
||
bgColor: '#E8F5E9',
|
||
badgeBg: '#C8E6C9',
|
||
textColor: '#1B5E20',
|
||
};
|
||
case 'PERCENTAGE_DISCOUNT':
|
||
return {
|
||
emoji: '🏷️',
|
||
bgColor: '#FFF3E0',
|
||
badgeBg: '#FFE0B2',
|
||
textColor: '#E65100',
|
||
};
|
||
case 'FLAT_DISCOUNT':
|
||
return {
|
||
emoji: '💰',
|
||
bgColor: '#E3F2FD',
|
||
badgeBg: '#BBDEFB',
|
||
textColor: '#0D47A1',
|
||
};
|
||
case 'BUY_ONE_GET_ONE':
|
||
return {
|
||
emoji: '🎁',
|
||
bgColor: '#F3E5F5',
|
||
badgeBg: '#E1BEE7',
|
||
textColor: '#4A148C',
|
||
};
|
||
default:
|
||
return {
|
||
emoji: '🎉',
|
||
bgColor: '#F5F5F5',
|
||
badgeBg: '#E0E0E0',
|
||
textColor: '#333333',
|
||
};
|
||
}
|
||
};
|
||
|
||
export const OffersScreen: React.FC = () => {
|
||
const { colors, isDarkMode } = useAppTheme();
|
||
const styles = getStyles(colors);
|
||
const dispatch = useAppDispatch();
|
||
const { offers, isLoading } = useAppSelector(state => state.offer);
|
||
|
||
const [copiedId, setCopiedId] = useState<string | null>(null);
|
||
|
||
useFocusEffect(
|
||
useCallback(() => {
|
||
dispatch(getAllOffersThunk());
|
||
}, [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 renderOfferCard = ({ item }: { item: Promotion }) => {
|
||
const visuals = getPromoVisuals(item.promotionType);
|
||
const isCopied = copiedId === item.id;
|
||
|
||
const hasFooter =
|
||
(item.minimumOrderAmount && item.minimumOrderAmount > 0) ||
|
||
(item.maximumDiscount && item.maximumDiscount > 0) ||
|
||
(item.applicableCategories && item.applicableCategories.length > 0) ||
|
||
(item.applicableProducts && item.applicableProducts.length > 0);
|
||
|
||
return (
|
||
<View style={styles.offerCard}>
|
||
{/* Main Card Header */}
|
||
<View style={styles.cardHeaderRow}>
|
||
<View style={[styles.iconWrap, { backgroundColor: visuals.bgColor }]}>
|
||
<Text style={styles.iconEmoji}>{visuals.emoji}</Text>
|
||
</View>
|
||
|
||
<View style={styles.offerInfo}>
|
||
{!!item.badgeText && (
|
||
<View
|
||
style={[
|
||
styles.badgeContainer,
|
||
{ backgroundColor: visuals.badgeBg },
|
||
]}
|
||
>
|
||
<Text style={[styles.badgeText, { color: visuals.textColor }]}>
|
||
{item.badgeText}
|
||
</Text>
|
||
</View>
|
||
)}
|
||
<Text style={styles.offerTitle}>{item.title}</Text>
|
||
{!!item.description && (
|
||
<Text style={styles.offerDescription}>{item.description}</Text>
|
||
)}
|
||
</View>
|
||
|
||
<TouchableOpacity
|
||
style={[styles.copyButton, isCopied && styles.copyButtonSuccess]}
|
||
// onPress={() => handleCopy(item)}
|
||
onPress={() => { }}
|
||
activeOpacity={0.8}
|
||
>
|
||
<Text style={styles.copyButtonText}>
|
||
{isCopied ? 'Copied ✓' : 'Copy'}
|
||
</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
|
||
{/* Dynamic Meta Details Footer (Only if real data exists) */}
|
||
{hasFooter && (
|
||
<View style={styles.cardFooter}>
|
||
{!!item.minimumOrderAmount && item.minimumOrderAmount > 0 && (
|
||
<View style={styles.metaChip}>
|
||
<Text style={styles.metaChipText}>
|
||
Min order ₹{item.minimumOrderAmount}
|
||
</Text>
|
||
</View>
|
||
)}
|
||
|
||
{!!item.maximumDiscount && item.maximumDiscount > 0 && (
|
||
<View style={styles.metaChip}>
|
||
<Text style={styles.metaChipText}>
|
||
Max discount ₹{item.maximumDiscount}
|
||
</Text>
|
||
</View>
|
||
)}
|
||
|
||
{!!item.applicableCategories?.length && (
|
||
<View style={styles.metaChip}>
|
||
<Text style={styles.metaChipText}>
|
||
{item.applicableCategories.length}{' '}
|
||
{item.applicableCategories.length === 1
|
||
? 'category'
|
||
: 'categories'}
|
||
</Text>
|
||
</View>
|
||
)}
|
||
|
||
{!!item.applicableProducts?.length && (
|
||
<View style={styles.metaChip}>
|
||
<Text style={styles.metaChipText}>
|
||
{item.applicableProducts.length}{' '}
|
||
{item.applicableProducts.length === 1 ? 'item' : 'items'}
|
||
</Text>
|
||
</View>
|
||
)}
|
||
</View>
|
||
)}
|
||
</View>
|
||
);
|
||
};
|
||
|
||
const renderSkeleton = () => (
|
||
<View style={styles.list}>
|
||
{[1, 2, 3].map(key => (
|
||
<View key={key} style={styles.skeletonCard}>
|
||
<View style={styles.skeletonLineShort} />
|
||
<View style={styles.skeletonLineLong} />
|
||
<View style={styles.skeletonLineSub} />
|
||
</View>
|
||
))}
|
||
</View>
|
||
);
|
||
|
||
const renderEmpty = () => (
|
||
<View style={styles.emptyWrap}>
|
||
<View style={styles.emptyIconWrap}>
|
||
<Text style={styles.emptyEmoji}>🏷️</Text>
|
||
</View>
|
||
<Text style={styles.emptyTitle}>No Offers Available</Text>
|
||
<Text style={styles.emptySubtitle}>
|
||
There are currently no active promotions.{'\n'}Check back later for
|
||
exciting discounts and deals!
|
||
</Text>
|
||
</View>
|
||
);
|
||
|
||
return (
|
||
<View style={styles.container}>
|
||
<StatusBar
|
||
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
|
||
backgroundColor={colors.background}
|
||
/>
|
||
<Header title="Offers" />
|
||
|
||
{isLoading && (!offers || offers.length === 0) ? (
|
||
renderSkeleton()
|
||
) : (
|
||
<FlatList
|
||
data={offers || []}
|
||
keyExtractor={item => item.id}
|
||
renderItem={renderOfferCard}
|
||
ListEmptyComponent={renderEmpty}
|
||
contentContainerStyle={styles.list}
|
||
showsVerticalScrollIndicator={false}
|
||
/>
|
||
)}
|
||
</View>
|
||
);
|
||
};
|
||
|