Handle error states and accessibility improvements

This commit is contained in:
2026-10-16 15:09:20 +02:00
parent fbd57d664f
commit 9b80580f9c
9 changed files with 139 additions and 42 deletions
+25 -2
View File
@@ -1,4 +1,4 @@
import { StyleSheet, Text, View } from 'react-native';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import PrimaryButton from '../components/PrimaryButton';
import AppHeader from '../components/layout/AppHeader';
@@ -8,7 +8,7 @@ import ProductCard from '../components/product/ProductCard';
import { calculateProductRating } from '../services/ratingService';
import { colors } from '../utils/constants';
export default function HomeScreen({ preferences, recentProducts, onStartScan, onOpenProduct }) {
export default function HomeScreen({ preferences, recentProducts, shoppingList, onStartScan, onOpenProduct, onOpenList }) {
const frequentProducts = [...recentProducts]
.filter((product) => (product.scanCount || 0) > 1)
.sort((a, b) => (b.scanCount || 0) - (a.scanCount || 0))
@@ -28,6 +28,14 @@ export default function HomeScreen({ preferences, recentProducts, onStartScan, o
Prüfe Allergien, Ernährung, Budget und Nachhaltigkeit direkt am Regal.
</Text>
<PrimaryButton label="Produkt scannen" onPress={onStartScan} />
{shoppingList?.items?.length > 0 ? (
<Pressable accessibilityRole="button" onPress={onOpenList} style={styles.listShortcut}>
<Text style={styles.listShortcutTitle}>Einkaufsliste</Text>
<Text style={styles.listShortcutCopy}>
{shoppingList.items.filter((item) => !item.checked).length} offene Produkte
</Text>
</Pressable>
) : null}
</View>
{frequentProducts.length > 0 ? (
@@ -119,5 +127,20 @@ const styles = StyleSheet.create({
fontSize: 14,
lineHeight: 20,
marginTop: 4
},
listShortcut: {
backgroundColor: '#eaf4ef',
borderRadius: 8,
gap: 2,
padding: 12
},
listShortcutTitle: {
color: colors.primaryDark,
fontSize: 15,
fontWeight: '800'
},
listShortcutCopy: {
color: colors.muted,
fontSize: 13
}
});
+17 -5
View File
@@ -30,9 +30,15 @@ export default function ScanScreen({ preferences, productCache, onScanBarcode, o
setIsScanning(false);
setIsLoadingProduct(true);
const result = await onScanBarcode(event.data).finally(() => {
let result;
try {
result = await onScanBarcode(event.data);
} catch (error) {
result = { status: 'error', errorMessage: 'Das Produkt konnte gerade nicht geladen werden.' };
} finally {
setIsLoadingProduct(false);
});
}
if (result?.status !== 'found') {
setScanError(result?.errorMessage || 'Der Barcode konnte nicht verarbeitet werden.');
@@ -41,10 +47,15 @@ export default function ScanScreen({ preferences, productCache, onScanBarcode, o
}
async function handleManualSearch() {
if (!manualSearchQuery.trim() || isSearching) return;
setIsSearching(true);
const results = await searchProducts(manualSearchQuery, productCache, preferences.offlineModeEnabled);
setManualResults(results);
setIsSearching(false);
try {
const results = await searchProducts(manualSearchQuery, productCache, preferences.offlineModeEnabled);
setManualResults(results);
} finally {
setIsSearching(false);
}
}
function retryScan() {
@@ -98,6 +109,7 @@ export default function ScanScreen({ preferences, productCache, onScanBarcode, o
<ManualSearchInput
onChangeText={setManualSearchQuery}
onSubmit={handleManualSearch}
disabled={isSearching}
value={manualSearchQuery}
/>
{isSearching ? <Text style={styles.note}>Suche läuft...</Text> : null}
+2 -2
View File
@@ -33,7 +33,7 @@ export default function ShoppingListScreen({
<View style={styles.summary}>
<Text style={styles.summaryTitle}>{shoppingList.title}</Text>
<Text style={styles.summaryCopy}>
Produkte abhaken, löschen oder nach dem Einkauf abschließen.
Produkte abhaken, löschen oder nach dem Einkauf abschliessen.
</Text>
<View style={styles.budgetBox}>
<View style={styles.budgetHeader}>
@@ -95,7 +95,7 @@ export default function ShoppingListScreen({
)}
{shoppingList.items.length > 0 ? (
<SecondaryButton label="Einkauf abschließen" onPress={onCompleteList} />
<SecondaryButton label="Einkauf abschliessen" onPress={onCompleteList} />
) : null}
</ScreenContainer>
);