113 lines
2.8 KiB
TypeScript
113 lines
2.8 KiB
TypeScript
import { TextInput, View, StyleSheet } from 'react-native';
|
|
import { ThemedText } from '@/components/themed-text';
|
|
import { useThemeColor } from '@/hooks/use-theme-color';
|
|
import { FormFieldSchema } from '@/lib/types/template-run';
|
|
|
|
interface NumberInputFieldProps {
|
|
field: FormFieldSchema;
|
|
value: number | string;
|
|
onChange: (value: number) => void;
|
|
error?: string;
|
|
}
|
|
|
|
export function NumberInputField({ field, value, onChange, error }: NumberInputFieldProps) {
|
|
const textColor = useThemeColor({}, 'text');
|
|
const borderColor = useThemeColor({}, 'border');
|
|
const errorColor = useThemeColor({}, 'error');
|
|
const placeholderColor = useThemeColor({}, 'textPlaceholder');
|
|
const backgroundColor = useThemeColor({}, 'background');
|
|
|
|
const handleChange = (text: string) => {
|
|
const num = parseFloat(text);
|
|
if (!isNaN(num)) {
|
|
onChange(num);
|
|
} else if (text === '') {
|
|
onChange(0);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
{field.label && (
|
|
<ThemedText style={styles.label}>
|
|
{field.label}
|
|
{field.required && <ThemedText style={[styles.required, { color: errorColor }]}> *</ThemedText>}
|
|
</ThemedText>
|
|
)}
|
|
|
|
<TextInput
|
|
style={[
|
|
styles.input,
|
|
{
|
|
color: textColor,
|
|
borderColor: error ? errorColor : borderColor,
|
|
backgroundColor,
|
|
}
|
|
]}
|
|
value={value?.toString() || ''}
|
|
onChangeText={handleChange}
|
|
placeholder={field.placeholder}
|
|
placeholderTextColor={placeholderColor}
|
|
keyboardType="numeric"
|
|
maxLength={10}
|
|
/>
|
|
|
|
{field.description && (
|
|
<ThemedText style={styles.description}>{field.description}</ThemedText>
|
|
)}
|
|
|
|
{error && (
|
|
<ThemedText style={[styles.errorText, { color: errorColor }]}>
|
|
{error}
|
|
</ThemedText>
|
|
)}
|
|
|
|
{(field.min !== undefined || field.max !== undefined) && (
|
|
<ThemedText style={styles.hint}>
|
|
{field.min !== undefined && field.max !== undefined
|
|
? `范围: ${field.min} - ${field.max}`
|
|
: field.min !== undefined
|
|
? `最小值: ${field.min}`
|
|
: `最大值: ${field.max}`}
|
|
</ThemedText>
|
|
)}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
marginBottom: 16,
|
|
},
|
|
label: {
|
|
fontSize: 16,
|
|
fontWeight: '600',
|
|
marginBottom: 8,
|
|
},
|
|
required: {
|
|
fontSize: 16,
|
|
fontWeight: '600',
|
|
},
|
|
input: {
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 10,
|
|
fontSize: 16,
|
|
minHeight: 44,
|
|
},
|
|
description: {
|
|
fontSize: 12,
|
|
opacity: 0.7,
|
|
marginTop: 4,
|
|
},
|
|
errorText: {
|
|
fontSize: 12,
|
|
marginTop: 4,
|
|
},
|
|
hint: {
|
|
fontSize: 12,
|
|
opacity: 0.6,
|
|
marginTop: 4,
|
|
},
|
|
}); |