225 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
};