Refactor profile screen layout and user preference handling
Android Release Build / build-android (push) Failing after 8m45s
Android Release Build / build-android (push) Failing after 8m45s
This commit is contained in:
@@ -0,0 +1,179 @@
|
|||||||
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
|
import AppHeader from '../components/layout/AppHeader';
|
||||||
|
import ScreenContainer from '../components/layout/ScreenContainer';
|
||||||
|
import ProductScoreBadge from '../components/product/ProductScoreBadge';
|
||||||
|
import { calculateProductRating } from '../services/ratingService';
|
||||||
|
import { colors } from '../utils/constants';
|
||||||
|
|
||||||
|
const labels = {
|
||||||
|
allergies: 'Allergien',
|
||||||
|
budget: 'Budget',
|
||||||
|
ingredients: 'Zutaten',
|
||||||
|
nutrition: 'Ernährung',
|
||||||
|
sustainability: 'Nachhaltigkeit'
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultDetails = {
|
||||||
|
allergies: {
|
||||||
|
positive: 'Keine blockierten Allergene und vollständige Allergenangaben verbessern diese Bewertung.',
|
||||||
|
penalty: 'Treffer mit deinen vermiedenen Allergenen setzen diese Kategorie hart nach unten. Fehlende Allergenangaben werden als Unsicherheit markiert.'
|
||||||
|
},
|
||||||
|
budget: {
|
||||||
|
positive: 'Ein niedriger Anteil am Budget pro Zeitraum verbessert diese Bewertung.',
|
||||||
|
penalty: 'Ein hoher Preis relativ zu deinem Budget reduziert die Bewertung. Fehlende Preise werden als ungenaue Prüfung markiert.'
|
||||||
|
},
|
||||||
|
ingredients: {
|
||||||
|
positive: 'Keine kritischen Zusatzstoffe, kein Palmöl und passende Vegan-/Vegetarisch-Analyse verbessern diese Bewertung.',
|
||||||
|
penalty: 'Kritische Zusatzstoffe, Palmöl, viele Zusatzstoffe oder ein Konflikt mit deinem Ernährungsziel reduzieren diese Bewertung.'
|
||||||
|
},
|
||||||
|
nutrition: {
|
||||||
|
positive: 'Guter Nutri-Score, niedrige kritische Nährwert-Level und passende Werte für dein Ernährungsziel verbessern diese Bewertung.',
|
||||||
|
penalty: 'Hohe Werte bei Zucker, Salz, Fett oder gesättigten Fettsäuren sowie Konflikte mit Low-Sugar- oder High-Protein-Zielen reduzieren diese Bewertung.'
|
||||||
|
},
|
||||||
|
sustainability: {
|
||||||
|
positive: 'Guter Eco-Score, niedriger CO2-Fussabdruck, regionale Herkunft, bessere Verpackung und Bio bei Bio-Präferenz verbessern diese Bewertung.',
|
||||||
|
penalty: 'Schwacher Eco-Score, hoher CO2-Fussabdruck, belastende Verpackung, weite Herkunft oder fehlendes Bio bei Bio-Präferenz reduzieren diese Bewertung.'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RatingCriteriaDetailScreen({ product, preferences, category, onBack }) {
|
||||||
|
const rating = calculateProductRating(product, preferences);
|
||||||
|
const categoryRating = rating.categoryScores[category];
|
||||||
|
const title = labels[category] || category;
|
||||||
|
const fallbackDetails = defaultDetails[category] || defaultDetails.ingredients;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ScreenContainer>
|
||||||
|
<AppHeader title={title} subtitle="Bewertungsdetail" onBack={onBack} />
|
||||||
|
|
||||||
|
<View style={styles.summaryPanel}>
|
||||||
|
<View style={styles.summaryRow}>
|
||||||
|
<View style={styles.summaryCopy}>
|
||||||
|
<Text style={styles.eyebrow}>Kriterium</Text>
|
||||||
|
<Text style={styles.title}>{title}</Text>
|
||||||
|
<Text style={styles.message}>{categoryRating.message}</Text>
|
||||||
|
</View>
|
||||||
|
<ProductScoreBadge status={categoryRating.status} score={categoryRating.score} />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{(categoryRating.missingData || []).length > 0 ? (
|
||||||
|
<View style={styles.panel}>
|
||||||
|
<Text style={styles.panelTitle}>Fehlende Daten</Text>
|
||||||
|
{categoryRating.missingData.map((message) => (
|
||||||
|
<Text key={message} style={styles.warningText}>{message}</Text>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{(categoryRating.details || []).length > 0 ? (
|
||||||
|
<View style={styles.panel}>
|
||||||
|
<Text style={styles.panelTitle}>So entsteht die Bewertung</Text>
|
||||||
|
{categoryRating.details.map((detail) => (
|
||||||
|
<View key={`${detail.title}-${detail.meta || ''}`} style={styles.detailItem}>
|
||||||
|
<Text style={detail.type === 'positive' ? styles.positiveTitle : styles.penaltyTitle}>
|
||||||
|
{detail.title}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.detailBody}>{detail.body}</Text>
|
||||||
|
{detail.meta ? <Text style={styles.detailMeta}>{detail.meta}</Text> : null}
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<View style={styles.panel}>
|
||||||
|
<Text style={styles.panelTitle}>Was die Bewertung verbessert</Text>
|
||||||
|
<Text style={styles.detailBody}>{fallbackDetails.positive}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.panel}>
|
||||||
|
<Text style={styles.panelTitle}>Was die Bewertung senkt</Text>
|
||||||
|
<Text style={styles.detailBody}>{fallbackDetails.penalty}</Text>
|
||||||
|
</View>
|
||||||
|
</ScreenContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
summaryPanel: {
|
||||||
|
backgroundColor: colors.surface,
|
||||||
|
borderColor: colors.border,
|
||||||
|
borderRadius: 18,
|
||||||
|
borderWidth: 1,
|
||||||
|
padding: 16
|
||||||
|
},
|
||||||
|
summaryRow: {
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: 12
|
||||||
|
},
|
||||||
|
summaryCopy: {
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
eyebrow: {
|
||||||
|
color: colors.primary,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: '800',
|
||||||
|
textTransform: 'uppercase'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
color: colors.text,
|
||||||
|
fontSize: 23,
|
||||||
|
fontWeight: '800',
|
||||||
|
lineHeight: 29,
|
||||||
|
marginTop: 4
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
color: colors.muted,
|
||||||
|
fontSize: 15,
|
||||||
|
lineHeight: 21,
|
||||||
|
marginTop: 8
|
||||||
|
},
|
||||||
|
panel: {
|
||||||
|
backgroundColor: colors.surface,
|
||||||
|
borderColor: colors.border,
|
||||||
|
borderRadius: 18,
|
||||||
|
borderWidth: 1,
|
||||||
|
gap: 10,
|
||||||
|
padding: 16
|
||||||
|
},
|
||||||
|
panelTitle: {
|
||||||
|
color: colors.text,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
detailItem: {
|
||||||
|
borderTopColor: colors.border,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
gap: 5,
|
||||||
|
paddingTop: 10
|
||||||
|
},
|
||||||
|
positiveTitle: {
|
||||||
|
color: colors.success,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
penaltyTitle: {
|
||||||
|
color: colors.danger,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '800'
|
||||||
|
},
|
||||||
|
detailBody: {
|
||||||
|
color: colors.muted,
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 20
|
||||||
|
},
|
||||||
|
detailMeta: {
|
||||||
|
color: colors.text,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '700',
|
||||||
|
lineHeight: 19
|
||||||
|
},
|
||||||
|
warningText: {
|
||||||
|
color: colors.warning,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: '700',
|
||||||
|
lineHeight: 19
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user