diff --git a/package-lock.json b/package-lock.json index 53774b3..37cf2b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@react-native-async-storage/async-storage": "2.1.2", + "@react-native-community/datetimepicker": "^9.1.0", "@react-native-community/netinfo": "11.4.1", "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/native": "^6.1.9", @@ -4911,6 +4912,29 @@ "node": ">=10" } }, + "node_modules/@react-native-community/datetimepicker": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-9.1.0.tgz", + "integrity": "sha512-eadbnk+I2vxvW30iTAsm/qlCnMMAadkifIMYNEB2lzhxN/SvlKc7S2V4k5DyrwjdCbqdcMk3t9K6fnUMcAV34w==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "expo": ">=52.0.0", + "react": "*", + "react-native": "*", + "react-native-windows": "*" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "react-native-windows": { + "optional": true + } + } + }, "node_modules/@react-native-community/netinfo": { "version": "11.4.1", "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-11.4.1.tgz", diff --git a/package.json b/package.json index 1d4f060..1e3e76c 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ }, "dependencies": { "@react-native-async-storage/async-storage": "2.1.2", + "@react-native-community/datetimepicker": "^9.1.0", "@react-native-community/netinfo": "11.4.1", "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/native": "^6.1.9", diff --git a/src/screens/AddSubscriptionScreen.tsx b/src/screens/AddSubscriptionScreen.tsx index 16ad15b..a4e806b 100644 --- a/src/screens/AddSubscriptionScreen.tsx +++ b/src/screens/AddSubscriptionScreen.tsx @@ -18,6 +18,8 @@ import { colors, spacing, typography, borderRadius } from '../utils/constants'; import { SubscriptionCategory, BillingCycle, SubscriptionFormData } from '../types/subscription'; import { useSubscriptionStore } from '../store'; import { Button } from '../components/common/Button'; +import { formatCurrency } from '../utils/formatting'; +import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker'; const AddSubscriptionScreen: React.FC = () => { const navigation = useNavigation>(); @@ -44,6 +46,10 @@ const AddSubscriptionScreen: React.FC = () => { BillingCycle.MONTHLY ); + // Date Picker States + const [showPicker, setShowPicker] = useState(false); + const [pickerMode, setPickerMode] = useState<'date' | 'time'>('date'); + const handleCategorySelect = (category: SubscriptionCategory) => { setSelectedCategory(category); setFormData((prev) => ({ ...prev, category })); @@ -56,11 +62,38 @@ const AddSubscriptionScreen: React.FC = () => { const handleInputChange = ( field: keyof SubscriptionFormData, - value: string | number | boolean + value: string | number | boolean | Date ) => { setFormData((prev) => ({ ...prev, [field]: value })); }; + const onDateChange = (event: DateTimePickerEvent, selectedDate?: Date) => { + if (event.type === 'dismissed') { + setShowPicker(false); + return; + } + + if (selectedDate) { + handleInputChange('nextBillingDate', selectedDate); + + if (Platform.OS === 'android' && pickerMode === 'date') { + setShowPicker(false); + setTimeout(() => { + setPickerMode('time'); + setShowPicker(true); + }, 100); + } else if (Platform.OS === 'android' && pickerMode === 'time') { + setShowPicker(false); + setPickerMode('date'); + } + } + }; + + const showPickerHandler = () => { + setPickerMode('date'); + setShowPicker(true); + }; + const handleSubmit = async () => { if (!formData.name.trim()) { Alert.alert('Error', 'Please enter a subscription name'); @@ -202,6 +235,32 @@ const AddSubscriptionScreen: React.FC = () => { + + Next Billing Date * + + + {formData.nextBillingDate.toLocaleString([], { + dateStyle: 'medium', + timeStyle: 'short', + })} + + + + {showPicker && ( + + )} + + Billing Cycle @@ -395,6 +454,19 @@ const styles = StyleSheet.create({ ...typography.h3, fontWeight: '600', }, + // Date picker styling + datePickerButton: { + backgroundColor: colors.surface, + padding: spacing.md, + borderRadius: borderRadius.md, + borderWidth: 1, + borderColor: colors.border, + justifyContent: 'center', + }, + datePickerText: { + ...typography.body, + color: colors.text, + }, categoryGrid: { flexDirection: 'row', flexWrap: 'wrap', @@ -495,4 +567,4 @@ const styles = StyleSheet.create({ }, }); -export default AddSubscriptionScreen; +export default AddSubscriptionScreen; \ No newline at end of file