wishlist
This commit is contained in:
@@ -10,10 +10,12 @@ import {
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { useCart } from '../../../hooks/useCart';
|
||||
import { useProduct } from '../../../hooks/useProducts';
|
||||
import { wishlistApi } from '../../../services/wishlistApi ';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
@@ -25,6 +27,8 @@ export default function ProductDetailScreen() {
|
||||
const { product, loading, error } = useProduct(productId);
|
||||
const { addToCart } = useCart();
|
||||
const [isAddingToCart, setIsAddingToCart] = useState(false);
|
||||
const [isInWishlist, setIsInWishlist] = useState(false);
|
||||
const [isLoadingWishlist, setIsLoadingWishlist] = useState(false);
|
||||
|
||||
const formatPrice = (price: number) => {
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
@@ -54,6 +58,35 @@ export default function ProductDetailScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleWishlist = async () => {
|
||||
if (!product) return;
|
||||
|
||||
setIsLoadingWishlist(true);
|
||||
try {
|
||||
if (isInWishlist) {
|
||||
const response = await wishlistApi.removeFromWishlist(product.productId);
|
||||
if (response.success) {
|
||||
setIsInWishlist(false);
|
||||
Alert.alert('Thành công', response.message);
|
||||
} else {
|
||||
Alert.alert('Lỗi', response.message);
|
||||
}
|
||||
} else {
|
||||
const response = await wishlistApi.addToWishlist(product.productId);
|
||||
if (response.success) {
|
||||
setIsInWishlist(true);
|
||||
Alert.alert('Thành công', response.message);
|
||||
} 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 {
|
||||
setIsLoadingWishlist(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
@@ -90,16 +123,37 @@ export default function ProductDetailScreen() {
|
||||
<Text style={styles.headerTitle} numberOfLines={1}>
|
||||
Chi tiết sản phẩm
|
||||
</Text>
|
||||
<View style={{ width: 40 }} />
|
||||
<TouchableOpacity
|
||||
style={styles.wishlistHeaderBtn}
|
||||
onPress={handleToggleWishlist}
|
||||
disabled={isLoadingWishlist}
|
||||
>
|
||||
{isLoadingWishlist ? (
|
||||
<ActivityIndicator size="small" color="#ff6b6b" />
|
||||
) : (
|
||||
<Ionicons
|
||||
name={isInWishlist ? 'heart' : 'heart-outline'}
|
||||
size={24}
|
||||
color={isInWishlist ? '#ff6b6b' : '#333'}
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
|
||||
{/* Product Image */}
|
||||
<Image
|
||||
source={{ uri: product.imageUrl || 'https://via.placeholder.com/400' }}
|
||||
style={styles.productImage}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
<View style={styles.imageContainer}>
|
||||
<Image
|
||||
source={{ uri: product.imageUrl || 'https://via.placeholder.com/400' }}
|
||||
style={styles.productImage}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
{product.stockQuantity <= 0 && (
|
||||
<View style={styles.outOfStockOverlay}>
|
||||
<Text style={styles.outOfStockText}>HẾT HÀNG</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Product Info */}
|
||||
<View style={styles.content}>
|
||||
@@ -182,6 +236,26 @@ export default function ProductDetailScreen() {
|
||||
|
||||
{/* Bottom Action Buttons */}
|
||||
<View style={styles.bottomActions}>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.actionButton,
|
||||
styles.wishlistActionButton,
|
||||
isInWishlist && styles.wishlistActionButtonActive,
|
||||
]}
|
||||
onPress={handleToggleWishlist}
|
||||
disabled={isLoadingWishlist}
|
||||
>
|
||||
{isLoadingWishlist ? (
|
||||
<ActivityIndicator size="small" color={isInWishlist ? '#fff' : '#ff6b6b'} />
|
||||
) : (
|
||||
<Ionicons
|
||||
name={isInWishlist ? 'heart' : 'heart-outline'}
|
||||
size={24}
|
||||
color={isInWishlist ? '#fff' : '#ff6b6b'}
|
||||
/>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.actionButton,
|
||||
@@ -249,14 +323,41 @@ const styles = StyleSheet.create({
|
||||
color: '#333',
|
||||
textAlign: 'center',
|
||||
},
|
||||
wishlistHeaderBtn: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
},
|
||||
productImage: {
|
||||
imageContainer: {
|
||||
position: 'relative',
|
||||
width: width,
|
||||
height: width,
|
||||
},
|
||||
productImage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: '#f0f0f0',
|
||||
},
|
||||
outOfStockOverlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
outOfStockText: {
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
color: '#fff',
|
||||
letterSpacing: 2,
|
||||
},
|
||||
content: {
|
||||
padding: 16,
|
||||
},
|
||||
@@ -308,9 +409,6 @@ const styles = StyleSheet.create({
|
||||
outOfStockBadge: {
|
||||
backgroundColor: '#ffebee',
|
||||
},
|
||||
outOfStockText: {
|
||||
color: '#f44336',
|
||||
},
|
||||
divider: {
|
||||
height: 1,
|
||||
backgroundColor: '#e0e0e0',
|
||||
@@ -369,6 +467,15 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 12,
|
||||
gap: 8,
|
||||
},
|
||||
wishlistActionButton: {
|
||||
flex: 0.5,
|
||||
backgroundColor: '#fff',
|
||||
borderWidth: 2,
|
||||
borderColor: '#ff6b6b',
|
||||
},
|
||||
wishlistActionButtonActive: {
|
||||
backgroundColor: '#ff6b6b',
|
||||
},
|
||||
addToCartButton: {
|
||||
backgroundColor: '#ff9800',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user