239 lines
7.1 KiB
TypeScript
239 lines
7.1 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import {
|
|
TouchableOpacity,
|
|
StyleSheet,
|
|
Text,
|
|
View,
|
|
Alert,
|
|
ActivityIndicator,
|
|
} from 'react-native';
|
|
import { AntDesign } from '@expo/vector-icons';
|
|
import { wishlistApi } from '../services/wishlistApi ';
|
|
|
|
interface WishlistButtonProps {
|
|
productId: number;
|
|
onToggle?: (isAdded: boolean) => void;
|
|
style?: any;
|
|
size?: 'small' | 'medium' | 'large';
|
|
showLabel?: boolean;
|
|
isInWishlist?: boolean;
|
|
}
|
|
|
|
const COLORS = {
|
|
primary: '#FF6B6B',
|
|
secondary: '#4ECDC4',
|
|
white: '#FFFFFF',
|
|
text: '#2C3E50',
|
|
lightText: '#95A5A6',
|
|
border: '#E0E0E0',
|
|
};
|
|
|
|
const WishlistButton: React.FC<WishlistButtonProps> = ({
|
|
productId,
|
|
onToggle,
|
|
style,
|
|
size = 'medium',
|
|
showLabel = false,
|
|
isInWishlist: initialIsInWishlist = false,
|
|
}) => {
|
|
const [isInWishlist, setIsInWishlist] = useState(initialIsInWishlist);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const getSizeStyles = () => {
|
|
switch (size) {
|
|
case 'small':
|
|
return {
|
|
buttonSize: 32,
|
|
iconSize: 16,
|
|
paddingHorizontal: 8,
|
|
paddingVertical: 4,
|
|
fontSize: 12,
|
|
};
|
|
case 'large':
|
|
return {
|
|
buttonSize: 56,
|
|
iconSize: 28,
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 12,
|
|
fontSize: 16,
|
|
};
|
|
default: // medium
|
|
return {
|
|
buttonSize: 44,
|
|
iconSize: 20,
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 8,
|
|
fontSize: 14,
|
|
};
|
|
}
|
|
};
|
|
|
|
const sizeStyles = getSizeStyles();
|
|
|
|
const handleToggleWishlist = async () => {
|
|
setLoading(true);
|
|
try {
|
|
if (isInWishlist) {
|
|
// Remove from wishlist
|
|
const response = await wishlistApi.removeFromWishlist(productId);
|
|
if (response.success) {
|
|
setIsInWishlist(false);
|
|
Alert.alert('Thành công', response.message);
|
|
onToggle?.(false);
|
|
} else {
|
|
Alert.alert('Lỗi', response.message);
|
|
}
|
|
} else {
|
|
// Add to wishlist
|
|
const response = await wishlistApi.addToWishlist(productId);
|
|
if (response.success) {
|
|
setIsInWishlist(true);
|
|
Alert.alert('Thành công', response.message);
|
|
onToggle?.(true);
|
|
} else {
|
|
Alert.alert('Lỗi', response.message);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
Alert.alert(
|
|
'Lỗi',
|
|
error instanceof Error ? error.message : 'Lỗi không xác định'
|
|
);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
if (size === 'large' && showLabel) {
|
|
return (
|
|
<TouchableOpacity
|
|
style={[styles.largeButtonContainer, style]}
|
|
onPress={handleToggleWishlist}
|
|
disabled={loading}
|
|
activeOpacity={0.7}
|
|
>
|
|
<View
|
|
style={[
|
|
styles.largeButton,
|
|
isInWishlist && styles.largeButtonActive,
|
|
]}
|
|
>
|
|
{loading ? (
|
|
<ActivityIndicator color={isInWishlist ? COLORS.white : COLORS.primary} />
|
|
) : (
|
|
<AntDesign
|
|
name={isInWishlist ? ('heart' as any) : ('hearto' as any)}
|
|
size={sizeStyles.iconSize}
|
|
color={isInWishlist ? COLORS.white : COLORS.primary}
|
|
/>
|
|
)}
|
|
<Text
|
|
style={[
|
|
styles.largeButtonLabel,
|
|
isInWishlist && styles.largeButtonLabelActive,
|
|
]}
|
|
>
|
|
{isInWishlist ? 'Đã yêu thích' : 'Yêu thích'}
|
|
</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.button,
|
|
{
|
|
width: sizeStyles.buttonSize,
|
|
height: sizeStyles.buttonSize,
|
|
borderRadius: sizeStyles.buttonSize / 2,
|
|
paddingHorizontal: sizeStyles.paddingHorizontal,
|
|
paddingVertical: sizeStyles.paddingVertical,
|
|
},
|
|
isInWishlist && styles.buttonActive,
|
|
style,
|
|
]}
|
|
onPress={handleToggleWishlist}
|
|
disabled={loading}
|
|
activeOpacity={0.7}
|
|
>
|
|
{loading ? (
|
|
<ActivityIndicator
|
|
color={isInWishlist ? COLORS.white : COLORS.primary}
|
|
/>
|
|
) : (
|
|
<>
|
|
<AntDesign
|
|
name={isInWishlist ? ('heart' as any) : ('hearto' as any)}
|
|
size={sizeStyles.iconSize}
|
|
color={isInWishlist ? COLORS.white : COLORS.primary}
|
|
/>
|
|
{showLabel && (
|
|
<Text
|
|
style={[
|
|
{ fontSize: sizeStyles.fontSize },
|
|
isInWishlist ? styles.labelActive : styles.label,
|
|
]}
|
|
>
|
|
{isInWishlist ? 'Đã thích' : 'Thích'}
|
|
</Text>
|
|
)}
|
|
</>
|
|
)}
|
|
</TouchableOpacity>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
button: {
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
backgroundColor: COLORS.white,
|
|
borderWidth: 2,
|
|
borderColor: COLORS.primary,
|
|
},
|
|
buttonActive: {
|
|
backgroundColor: COLORS.primary,
|
|
borderColor: COLORS.primary,
|
|
},
|
|
label: {
|
|
color: COLORS.primary,
|
|
fontWeight: '600',
|
|
marginTop: 4,
|
|
},
|
|
labelActive: {
|
|
color: COLORS.white,
|
|
fontWeight: '600',
|
|
marginTop: 4,
|
|
},
|
|
largeButtonContainer: {
|
|
width: '100%',
|
|
},
|
|
largeButton: {
|
|
flexDirection: 'row',
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 12,
|
|
borderRadius: 8,
|
|
backgroundColor: COLORS.white,
|
|
borderWidth: 2,
|
|
borderColor: COLORS.primary,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
gap: 8,
|
|
},
|
|
largeButtonActive: {
|
|
backgroundColor: COLORS.primary,
|
|
borderColor: COLORS.primary,
|
|
},
|
|
largeButtonLabel: {
|
|
fontSize: 16,
|
|
fontWeight: '700',
|
|
color: COLORS.primary,
|
|
},
|
|
largeButtonLabelActive: {
|
|
color: COLORS.white,
|
|
},
|
|
});
|
|
|
|
export default WishlistButton; |