Skip to content

Commit a63b2d0

Browse files
author
OpenClaw Agent
committed
refactor(pigeon-list): clean up and finalize MD3 design
- Complete rewrite of PigeonListScreen with proper state handling - Removed old Input/Card imports, using MD3 SearchBar only - Fixed empty states (no data vs no search results) - Cleaner FAB positioning - removed unused imports (ListTile, Avatar)
1 parent 9727f45 commit a63b2d0

1 file changed

Lines changed: 45 additions & 64 deletions

File tree

mobile/src/screens/pigeons/PigeonListScreen.tsx

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,25 @@ import React, { useState, useCallback } from 'react';
22
import {
33
View,
44
StyleSheet,
5-
RefreshControl,
65
ActivityIndicator,
76
TouchableOpacity,
87
} from 'react-native';
98
import { usePigeonsNavigation } from '../../navigation/hooks';
109
import { Text } from '../../components/atoms/Text';
1110
import { Button } from '../../components/atoms/Button';
12-
import { Input } from '../../components/atoms/Input';
13-
import { Card } from '../../components/atoms/Card';
1411
import { Icon } from '../../components/atoms/Icon';
1512
import { PigeonList } from './components/PigeonList';
1613
import { usePigeons } from '../../hooks/queries';
1714
import { useDebounce } from '../../hooks';
1815
import { useTheme } from '../../theme';
1916
import { spacing } from '../../theme/spacing';
2017
import { SearchBar } from '../../components/molecules/SearchBar';
21-
import { ListTile } from '../../components/molecules/ListTile';
22-
import { Avatar } from '../../components/atoms/Avatar';
2318

2419
export const PigeonListScreen: React.FC = () => {
2520
const navigation = usePigeonsNavigation();
2621
const theme = useTheme();
2722
const [page, setPage] = useState(1);
2823
const [searchQuery, setSearchQuery] = useState('');
29-
const [refreshing, setRefreshing] = useState(false);
3024

3125
const debouncedSearch = useDebounce(searchQuery, 500);
3226
const effectiveSearch = debouncedSearch;
@@ -37,14 +31,6 @@ export const PigeonListScreen: React.FC = () => {
3731
search: effectiveSearch || undefined,
3832
});
3933

40-
41-
const handleRefresh = useCallback(async () => {
42-
setRefreshing(true);
43-
setPage(1);
44-
await refetch();
45-
setRefreshing(false);
46-
}, [refetch]);
47-
4834
const handleEndReached = useCallback(() => {
4935
if (data?.pagination && page < data.pagination.pages) {
5036
setPage((p) => p + 1);
@@ -62,19 +48,7 @@ export const PigeonListScreen: React.FC = () => {
6248
navigation.navigate({ name: 'NewPigeon', params: {} });
6349
}, [navigation]);
6450

65-
// Loading state
66-
if (isLoading && !refreshing) {
67-
return (
68-
<View style={styles.centered}>
69-
<ActivityIndicator size="large" color={theme.colors.primary} />
70-
<Text variant="body" color={theme.colors.onSurfaceVariant} style={styles.loadingText}>
71-
Tauben werden geladen...
72-
</Text>
73-
</View>
74-
);
75-
}
76-
77-
// ERROR state - NEU!
51+
// ERROR state
7852
if (isError) {
7953
return (
8054
<View style={styles.centered}>
@@ -92,41 +66,57 @@ export const PigeonListScreen: React.FC = () => {
9266
);
9367
}
9468

95-
// Empty state - keine Suchergebnisse
96-
if (!data?.pigeons?.length && !isLoading && searchQuery) {
69+
// Loading state
70+
if (isLoading) {
71+
return (
72+
<View style={styles.centered}>
73+
<ActivityIndicator size="large" color={theme.colors.primary} />
74+
<Text variant="body" color={theme.colors.onSurfaceVariant} style={styles.loadingText}>
75+
Tauben werden geladen...
76+
</Text>
77+
</View>
78+
);
79+
}
80+
81+
// Empty state - keine Daten UND keine Suche
82+
if (!data?.pigeons?.length && !searchQuery) {
9783
return (
9884
<View style={styles.container}>
99-
<Card style={styles.searchCard}>
100-
<Input
101-
placeholder="Name suchen..."
102-
value={searchQuery}
103-
onChangeText={setSearchQuery}
104-
leftIcon="magnify"
105-
rightIcon="close"
106-
onRightIconPress={() => setSearchQuery('')}
107-
blurOnSubmit={false}
108-
returnKeyType="search"
109-
autoFocus={true}
110-
/>
111-
</Card>
85+
<Text variant="h1" style={styles.headerTitle}>
86+
Tauben
87+
</Text>
88+
89+
<SearchBar
90+
value={searchQuery}
91+
onChangeText={setSearchQuery}
92+
onClear={() => setSearchQuery('')}
93+
placeholder="Tauben suchen..."
94+
/>
11295

11396
<View style={styles.centered}>
114-
<Icon name="magnify-close" size={64} color={theme.colors.onSurfaceVariant} />
97+
<Icon name="bird" size={64} color={theme.colors.onSurfaceVariant} />
11598
<Text variant="h3" style={styles.emptyTitle}>
116-
Keine Ergebnisse
99+
Keine Tauben gefunden
117100
</Text>
118101
<Text variant="body" color={theme.colors.onSurfaceVariant} style={styles.emptyText}>
119-
Keine Tauben gefunden für "{searchQuery}"
102+
Füge deine erste Taube hinzu oder starte einen Scan.
120103
</Text>
121-
<Button variant="secondary" onPress={() => setSearchQuery('')} style={styles.addButton}>
122-
Suche zurücksetzen
104+
<Button variant="primary" onPress={handleAddPigeon} style={styles.addButton}>
105+
Taube hinzufügen
123106
</Button>
124107
</View>
125108
</View>
126109
);
127110
}
111+
112+
// Empty state - Suche ohne Ergebnisse
113+
if (!data?.pigeons?.length && searchQuery) {
128114
return (
129115
<View style={styles.container}>
116+
<Text variant="h1" style={styles.headerTitle}>
117+
Tauben
118+
</Text>
119+
130120
<SearchBar
131121
value={searchQuery}
132122
onChangeText={setSearchQuery}
@@ -135,15 +125,15 @@ export const PigeonListScreen: React.FC = () => {
135125
/>
136126

137127
<View style={styles.centered}>
138-
<Icon name="bird" size={64} color={theme.colors.onSurfaceVariant} />
128+
<Icon name="magnify-close" size={64} color={theme.colors.onSurfaceVariant} />
139129
<Text variant="h3" style={styles.emptyTitle}>
140-
Keine Tauben gefunden
130+
Keine Ergebnisse
141131
</Text>
142132
<Text variant="body" color={theme.colors.onSurfaceVariant} style={styles.emptyText}>
143-
Füge deine erste Taube hinzu oder starte einen Scan.
133+
Keine Tauben gefunden für "{searchQuery}"
144134
</Text>
145-
<Button variant="primary" onPress={handleAddPigeon} style={styles.addButton}>
146-
Taube hinzufügen
135+
<Button variant="secondary" onPress={() => setSearchQuery('')} style={styles.addButton}>
136+
Suche zurücksetzen
147137
</Button>
148138
</View>
149139
</View>
@@ -169,11 +159,11 @@ export const PigeonListScreen: React.FC = () => {
169159
pigeons={data?.pigeons || []}
170160
onPigeonPress={handlePigeonPress}
171161
onEndReached={handleEndReached}
172-
isLoadingMore={isFetching && !!data?.pigeons?.length}
162+
isLoadingMore={isFetching}
173163
/>
174164
</View>
175165

176-
{/* Floating Add FAB - nur Icon */}
166+
{/* Floating Add FAB */}
177167
<TouchableOpacity
178168
style={[styles.fab, { backgroundColor: theme.colors.primary }]}
179169
onPress={handleAddPigeon}
@@ -194,11 +184,6 @@ const styles = StyleSheet.create({
194184
marginHorizontal: spacing.md,
195185
marginBottom: 8,
196186
},
197-
searchCard: {
198-
margin: spacing.md,
199-
marginBottom: 0,
200-
padding: spacing.md,
201-
},
202187
listContainer: {
203188
flex: 1,
204189
},
@@ -210,7 +195,6 @@ const styles = StyleSheet.create({
210195
},
211196
loadingText: {
212197
marginTop: spacing.md,
213-
214198
},
215199
emptyTitle: {
216200
marginTop: spacing.lg,
@@ -219,18 +203,15 @@ const styles = StyleSheet.create({
219203
},
220204
emptyText: {
221205
textAlign: 'center',
222-
223206
marginBottom: spacing.lg,
224207
},
225208
addButton: {
226209
marginTop: spacing.md,
227210
},
228-
fabContainer: {
211+
fab: {
229212
position: 'absolute',
230213
right: spacing.lg,
231214
bottom: spacing.lg,
232-
},
233-
fab: {
234215
width: 56,
235216
height: 56,
236217
borderRadius: 28,

0 commit comments

Comments
 (0)