118 lines
2.9 KiB
TypeScript
118 lines
2.9 KiB
TypeScript
import React from 'react';
|
|
import { View, TextInput, TouchableOpacity, Text, StyleSheet } from 'react-native';
|
|
import { MaterialIcons } from '@expo/vector-icons';
|
|
import type { ComponentProps } from 'react';
|
|
|
|
type IconName = ComponentProps<typeof MaterialIcons>['name'];
|
|
|
|
export interface SearchFilters {
|
|
name: boolean;
|
|
ocrText: boolean;
|
|
}
|
|
|
|
export type SortKey = 'date' | 'name' | 'size';
|
|
export type SortDirection = 'asc' | 'desc';
|
|
|
|
export interface SortState {
|
|
key: SortKey;
|
|
direction: SortDirection;
|
|
}
|
|
|
|
interface SearchBarProps {
|
|
query: string;
|
|
onQueryChange: (q: string) => void;
|
|
onClear: () => void;
|
|
filters: SearchFilters;
|
|
onFiltersChange: (f: SearchFilters) => void;
|
|
onSettingsPress: () => void;
|
|
sort: SortState;
|
|
bottomPadding?: number;
|
|
}
|
|
|
|
export function SearchBar({ query, onQueryChange, onClear, filters, onSettingsPress, sort, bottomPadding = 0 }: SearchBarProps) {
|
|
const hasActiveFilter = filters.name || filters.ocrText || sort.key !== 'date';
|
|
|
|
return (
|
|
<View style={[styles.wrapper, { paddingBottom: bottomPadding }]}>
|
|
<View style={styles.inputRow}>
|
|
<View style={styles.inputContainer}>
|
|
<MaterialIcons name="search" size={20} color="#999" style={styles.searchIcon} />
|
|
<TextInput
|
|
style={styles.input}
|
|
placeholder="Rechercher..."
|
|
placeholderTextColor="#999"
|
|
value={query}
|
|
onChangeText={onQueryChange}
|
|
returnKeyType="search"
|
|
autoCorrect={false}
|
|
/>
|
|
{query.length > 0 && (
|
|
<TouchableOpacity onPress={onClear} style={styles.clearBtn}>
|
|
<MaterialIcons name="close" size={18} color="#999" />
|
|
</TouchableOpacity>
|
|
)}
|
|
</View>
|
|
|
|
<TouchableOpacity
|
|
style={[styles.iconBtn, hasActiveFilter && styles.iconBtnActive]}
|
|
onPress={onSettingsPress}
|
|
>
|
|
<MaterialIcons
|
|
name="tune"
|
|
size={22}
|
|
color={hasActiveFilter ? '#fff' : '#1976D2'}
|
|
/>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
wrapper: {
|
|
backgroundColor: '#fff',
|
|
borderTopWidth: 1,
|
|
borderTopColor: '#e0e0e0',
|
|
},
|
|
inputRow: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 10,
|
|
gap: 8,
|
|
},
|
|
inputContainer: {
|
|
flex: 1,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: '#f5f5f5',
|
|
borderRadius: 10,
|
|
paddingHorizontal: 10,
|
|
},
|
|
searchIcon: {
|
|
marginRight: 6,
|
|
},
|
|
input: {
|
|
flex: 1,
|
|
paddingVertical: 8,
|
|
fontSize: 14,
|
|
color: '#333',
|
|
},
|
|
clearBtn: {
|
|
padding: 4,
|
|
},
|
|
iconBtn: {
|
|
width: 40,
|
|
height: 40,
|
|
borderRadius: 10,
|
|
borderWidth: 1,
|
|
borderColor: '#1976D2',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
backgroundColor: '#fff',
|
|
},
|
|
iconBtnActive: {
|
|
backgroundColor: '#1976D2',
|
|
},
|
|
});
|