Show product images
This commit is contained in:
@@ -2,19 +2,25 @@ import { Pressable, StyleSheet, Text, View } from 'react-native';
|
|||||||
|
|
||||||
import { colors } from '../../utils/constants';
|
import { colors } from '../../utils/constants';
|
||||||
import { formatPrice } from '../../utils/formatPrice';
|
import { formatPrice } from '../../utils/formatPrice';
|
||||||
|
import ProductImage from './ProductImage';
|
||||||
import ProductScoreBadge from './ProductScoreBadge';
|
import ProductScoreBadge from './ProductScoreBadge';
|
||||||
|
|
||||||
export default function ProductCard({ product, rating, onPress }) {
|
export default function ProductCard({ product, rating, onPress }) {
|
||||||
return (
|
return (
|
||||||
<Pressable accessibilityRole="button" onPress={onPress} style={styles.card}>
|
<Pressable accessibilityRole="button" onPress={onPress} style={styles.card}>
|
||||||
<View style={styles.topRow}>
|
<View style={styles.topRow}>
|
||||||
|
<ProductImage imageUrl={product.imageUrl} />
|
||||||
<View style={styles.copy}>
|
<View style={styles.copy}>
|
||||||
<Text style={styles.name}>{product.name}</Text>
|
<Text style={styles.name}>{product.name}</Text>
|
||||||
<Text style={styles.meta}>{product.brand || 'Ohne Marke'} · {formatPrice(product.price, product.currency)}</Text>
|
<Text style={styles.meta}>
|
||||||
|
{product.brand || 'Ohne Marke'} · {formatPrice(product.price, product.currency)}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.note}>
|
||||||
|
{product.category || 'Produkt'} · Barcode {product.barcode}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
{rating ? <ProductScoreBadge status={rating.overallStatus} score={rating.overallScore} /> : null}
|
{rating ? <ProductScoreBadge status={rating.overallStatus} score={rating.overallScore} /> : null}
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.note}>{product.category || 'Produkt'} · Barcode {product.barcode}</Text>
|
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -48,6 +54,8 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
note: {
|
note: {
|
||||||
color: colors.muted,
|
color: colors.muted,
|
||||||
fontSize: 13
|
fontSize: 13,
|
||||||
|
lineHeight: 18,
|
||||||
|
marginTop: 8
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { Image, StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
|
import { colors } from '../../utils/constants';
|
||||||
|
|
||||||
|
export default function ProductImage({ imageUrl, size = 'card' }) {
|
||||||
|
const style = size === 'large' ? styles.large : styles.card;
|
||||||
|
|
||||||
|
if (!imageUrl) {
|
||||||
|
return (
|
||||||
|
<View style={[styles.placeholder, style]}>
|
||||||
|
<Text style={styles.placeholderText}>Kein Bild</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
accessibilityIgnoresInvertColors
|
||||||
|
resizeMode="contain"
|
||||||
|
source={{ uri: imageUrl }}
|
||||||
|
style={[styles.image, style]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
image: {
|
||||||
|
backgroundColor: colors.surface,
|
||||||
|
borderColor: colors.border,
|
||||||
|
borderWidth: 1
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
borderRadius: 8,
|
||||||
|
height: 76,
|
||||||
|
width: 76
|
||||||
|
},
|
||||||
|
large: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
borderRadius: 8,
|
||||||
|
height: 220,
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#eef3ef',
|
||||||
|
borderColor: colors.border,
|
||||||
|
borderWidth: 1,
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
placeholderText: {
|
||||||
|
color: colors.muted,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: '800',
|
||||||
|
textAlign: 'center'
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -6,6 +6,7 @@ import SecondaryButton from '../components/SecondaryButton';
|
|||||||
import AppHeader from '../components/layout/AppHeader';
|
import AppHeader from '../components/layout/AppHeader';
|
||||||
import ScreenContainer from '../components/layout/ScreenContainer';
|
import ScreenContainer from '../components/layout/ScreenContainer';
|
||||||
import SectionTitle from '../components/layout/SectionTitle';
|
import SectionTitle from '../components/layout/SectionTitle';
|
||||||
|
import ProductImage from '../components/product/ProductImage';
|
||||||
import ProductScoreBadge from '../components/product/ProductScoreBadge';
|
import ProductScoreBadge from '../components/product/ProductScoreBadge';
|
||||||
import RatingCategoryRow from '../components/product/RatingCategoryRow';
|
import RatingCategoryRow from '../components/product/RatingCategoryRow';
|
||||||
import { calculateProductRating } from '../services/ratingService';
|
import { calculateProductRating } from '../services/ratingService';
|
||||||
@@ -26,6 +27,7 @@ export default function ProductDetailScreen({ product, preferences, onBack, onAd
|
|||||||
<AppHeader title="Produktbewertung" subtitle="Persönliche Einschätzung" onBack={onBack} />
|
<AppHeader title="Produktbewertung" subtitle="Persönliche Einschätzung" onBack={onBack} />
|
||||||
|
|
||||||
<View style={styles.productPanel}>
|
<View style={styles.productPanel}>
|
||||||
|
<ProductImage imageUrl={product.imageUrl} size="large" />
|
||||||
<View style={styles.topRow}>
|
<View style={styles.topRow}>
|
||||||
<View style={styles.copy}>
|
<View style={styles.copy}>
|
||||||
<Text style={styles.brand}>{product.brand || 'Ohne Marke'}</Text>
|
<Text style={styles.brand}>{product.brand || 'Ohne Marke'}</Text>
|
||||||
|
|||||||
Reference in New Issue
Block a user