This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import React from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
|
||||
import { useCategories } from '@/hooks/useDatabase';
|
||||
import { useSettings } from '@/theme';
|
||||
|
||||
interface CategorySelectorProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function CategorySelector({ value, onChange, error }: CategorySelectorProps) {
|
||||
const categories = useCategories();
|
||||
const { theme } = useSettings();
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={[styles.label, { color: theme.text }]}>Category</Text>
|
||||
<View style={styles.requiredIndicator} />
|
||||
<ScrollView
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
style={styles.scrollView}
|
||||
>
|
||||
{categories.map((category) => (
|
||||
<TouchableOpacity
|
||||
key={category.id}
|
||||
style={[
|
||||
styles.categoryButton,
|
||||
{ backgroundColor: theme.card, borderColor: theme.borderStrong },
|
||||
value === category.id && { borderColor: theme.accent, backgroundColor: theme.accentSoft, borderWidth: 2 },
|
||||
]}
|
||||
onPress={() => onChange(category.id)}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.colorCircle,
|
||||
{ backgroundColor: category.color },
|
||||
value === category.id && styles.colorCircleSelected,
|
||||
]}
|
||||
/>
|
||||
<Text style={[
|
||||
styles.categoryName,
|
||||
{ color: theme.textSecondary },
|
||||
value === category.id && { color: theme.accent, fontWeight: '600' },
|
||||
]}>
|
||||
{category.name}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
{error && <Text style={styles.errorText}>{error}</Text>}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
gap: 8,
|
||||
},
|
||||
label: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
requiredIndicator: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
color: '#E53935',
|
||||
fontSize: 14,
|
||||
},
|
||||
scrollView: {
|
||||
paddingVertical: 4,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 16,
|
||||
gap: 10,
|
||||
},
|
||||
categoryButton: {
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 10,
|
||||
borderRadius: 24,
|
||||
borderWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
minWidth: 90,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
colorCircle: {
|
||||
width: 12,
|
||||
height: 12,
|
||||
borderRadius: 6,
|
||||
},
|
||||
colorCircleSelected: {
|
||||
width: 14,
|
||||
height: 14,
|
||||
borderRadius: 7,
|
||||
},
|
||||
categoryName: {
|
||||
fontSize: 13,
|
||||
fontWeight: '500',
|
||||
},
|
||||
errorText: {
|
||||
fontSize: 12,
|
||||
color: '#E53935',
|
||||
marginLeft: 16,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user