Skip to content

Commit e7641ba

Browse files
authored
Merge pull request #154 from internet-dot/fix/issue-44
fix: add price parsing edge case handling
2 parents 5f0891b + 27a3833 commit e7641ba

1 file changed

Lines changed: 29 additions & 4 deletions

File tree

src/screens/AddSubscriptionScreen.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const AddSubscriptionScreen: React.FC = () => {
2929
description: '',
3030
category: SubscriptionCategory.OTHER,
3131
price: 0,
32+
priceError: '',
3233
currency: 'USD',
3334
billingCycle: BillingCycle.MONTHLY,
3435
nextBillingDate: new Date(),
@@ -99,8 +100,8 @@ const AddSubscriptionScreen: React.FC = () => {
99100
return;
100101
}
101102

102-
if (formData.price <= 0) {
103-
Alert.alert('Error', 'Please enter a valid price');
103+
if (formData.priceError || !formData.price || formData.price <= 0 || Number.isNaN(formData.price)) {
104+
Alert.alert('Error', formData.priceError || 'Please enter a valid price');
104105
return;
105106
}
106107

@@ -149,7 +150,7 @@ const AddSubscriptionScreen: React.FC = () => {
149150
<KeyboardAvoidingView
150151
style={styles.keyboardAvoidingView}
151152
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
152-
<ScrollView style={styles.scrollView}>
153+
<ScrollView style={styles.scrollView} keyboardShouldPersistTaps="handled">
153154
<View style={styles.header}>
154155
<View style={styles.headerContent}>
155156
<TouchableOpacity onPress={handleCancel} style={styles.cancelButton}>
@@ -224,14 +225,33 @@ const AddSubscriptionScreen: React.FC = () => {
224225
style={styles.priceInput}
225226
value={formData.price > 0 ? formData.price.toString() : ''}
226227
onChangeText={(text) => {
227-
const numValue = parseFloat(text) || 0;
228+
if (text.trim() === '') {
229+
handleInputChange('priceError', '');
230+
handleInputChange('price', 0);
231+
return;
232+
}
233+
// Reject non-numeric input (allow digits, one dot, leading/trailing spaces)
234+
if (!/^[\d.,\s]*$/.test(text.trim())) {
235+
handleInputChange('priceError', 'Price must be a valid number');
236+
return;
237+
}
238+
const normalized = text.replace(/,/g, '.').trim();
239+
const numValue = parseFloat(normalized);
240+
if (Number.isNaN(numValue)) {
241+
handleInputChange('priceError', 'Price must be a valid number');
242+
} else {
243+
handleInputChange('priceError', '');
244+
}
228245
handleInputChange('price', numValue);
229246
}}
230247
placeholder="0.00"
231248
placeholderTextColor={colors.textSecondary}
232249
keyboardType="decimal-pad"
233250
/>
234251
</View>
252+
{formData.priceError ? (
253+
<Text style={styles.errorText}>{formData.priceError}</Text>
254+
) : null}
235255
</View>
236256

237257
<View style={styles.inputGroup}>
@@ -416,6 +436,11 @@ const styles = StyleSheet.create({
416436
marginBottom: spacing.xs,
417437
fontWeight: '500',
418438
},
439+
errorText: {
440+
color: colors.error || '#e74c3c',
441+
fontSize: 12,
442+
marginTop: spacing.xs,
443+
},
419444
textInput: {
420445
backgroundColor: colors.surface,
421446
padding: spacing.md,

0 commit comments

Comments
 (0)