Skip to content

Commit

Permalink
Fix: date and time pickers issues on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
aelassas committed Feb 16, 2025
1 parent 8c25d9b commit 281d389
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 78 deletions.
153 changes: 75 additions & 78 deletions mobile/components/DateTimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import React, { useState, useEffect } from 'react'
import {
StyleSheet,
View,
Pressable,
Text
} from 'react-native'
import ReactDateTimePicker from '@react-native-community/datetimepicker'
import React, { useState, useEffect, useCallback } from 'react'
import { StyleSheet, View, Pressable, Text, Platform, StyleProp, ViewStyle } from 'react-native'
import DateTimePicker from '@react-native-community/datetimepicker'
import DateTimePickerModal from 'react-native-modal-datetime-picker'
import { format } from 'date-fns'
import { enUS, fr } from 'date-fns/locale'
import { enUS, fr, es } from 'date-fns/locale'
import { MaterialIcons } from '@expo/vector-icons'
import * as movininHelper from ':movinin-helper'
import * as helper from '@/common/helper'

interface DateTimePickerProps {
value?: Date
locale?: string,
mode?: 'date' | 'datetime' | 'time' | 'countdown'
mode?: 'date' | 'datetime' | 'time'
size?: 'small'
label: string
backgroundColor?: string
error?: boolean
style?: object
style?: StyleProp<ViewStyle>
helperText?: string
minDate?: Date
maxDate?: Date
Expand All @@ -32,12 +28,12 @@ interface DateTimePickerProps {
onChange?: (date: Date | undefined) => void
}

const DateTimePicker = ({
value: dateTimeValue,
locale: dateTimeLocale,
mode,
const CustomDateTimePicker: React.FC<DateTimePickerProps> = ({
value: initialValue,
locale: initialLocale = 'en',
mode = 'date',
size,
label: dateTimeLabel,
label,
backgroundColor,
error,
style,
Expand All @@ -50,29 +46,41 @@ const DateTimePicker = ({
hidePickerMessage,
onPress,
onChange
}: DateTimePickerProps) => {
const [label, setLabel] = useState('')
const [value, setValue] = useState<Date | undefined>(dateTimeValue)
const [show, setShow] = useState(false)
const [locale, setLoacle] = useState(dateTimeLocale === 'fr' ? fr : enUS)
const _format = mode === 'date' ? 'eeee, d LLLL yyyy' : 'kk:mm'
const now = new Date()
}) => {
const [selectedDate, setSelectedDate] = useState<Date | undefined>(initialValue)
const [showPicker, setShowPicker] = useState(false)
const [formattedLabel, setFormattedLabel] = useState(label)

const localeMap = { fr, es, en: enUS }
const dateLocale = localeMap[initialLocale as keyof typeof localeMap] || enUS
const dateFormat = mode === 'date' ? 'eeee, d LLLL yyyy' : 'kk:mm'
const small = size === 'small'

useEffect(() => {
const _locale = dateTimeLocale === 'fr' ? fr : enUS
setLoacle(_locale)
setLabel((value && movininHelper.capitalize(format(value, _format, { locale: _locale }))) || dateTimeLabel)
}, [dateTimeLocale]) // eslint-disable-line react-hooks/exhaustive-deps
if (selectedDate) {
setFormattedLabel(movininHelper.capitalize(format(selectedDate, dateFormat, { locale: dateLocale })))
} else {
setFormattedLabel(label)
}
}, [selectedDate, initialLocale]) // eslint-disable-line react-hooks/exhaustive-deps

useEffect(() => {
setValue(dateTimeValue)
setLabel((dateTimeValue && movininHelper.capitalize(format(dateTimeValue, _format, { locale }))) || dateTimeLabel)
}, [dateTimeValue]) // eslint-disable-line react-hooks/exhaustive-deps
setSelectedDate(initialValue)
}, [initialValue])

useEffect(() => {
const handleDateChange = useCallback((date?: Date) => {
setShowPicker(false)
if (date) {
setSelectedDate(date)
onChange?.(date)
}
}, [onChange])

}, [dateTimeValue])
const handleClear = useCallback(() => {
setSelectedDate(undefined)
setFormattedLabel(label)
onChange?.(undefined)
}, [label, onChange])

const styles = StyleSheet.create({
container: {
Expand Down Expand Up @@ -127,68 +135,57 @@ const DateTimePicker = ({
})

return (
<View style={{ ...style, ...styles.container }}>
{value && <Text style={styles.label}>{dateTimeLabel}</Text>}
<View style={[styles.container, style]}>
{selectedDate && <Text style={styles.label}>{label}</Text>}

<View style={styles.dateContainer}>
<Pressable
style={styles.dateButton}
onPress={() => {
if (hidePicker && hidePickerMessage) {
helper.toast(hidePickerMessage)
} else {
setShow(true)

if (onPress) {
onPress()
}
setShowPicker(true)
onPress?.()
}
}}
>
<Text
style={{
...styles.dateText,
color: value ? 'rgba(0, 0, 0, 0.87)' : 'rgba(0, 0, 0, .4)',
}}
>
{label}
<Text style={[styles.dateText, { color: selectedDate ? 'rgba(0, 0, 0, 0.87)' : '#a3a3a3' }]}>
{formattedLabel}
</Text>
{!readOnly && value !== undefined && !hideClearButton && (
<MaterialIcons
style={styles.clear}
name="clear"
size={22}
color="rgba(0, 0, 0, 0.28)"
onPress={() => {
setLabel(dateTimeLabel)
setValue(undefined)
if (onChange) {
onChange(undefined)
}
}}
/>

{!readOnly && selectedDate && !hideClearButton && (
<MaterialIcons style={styles.clear} name="clear" size={22} color="rgba(0, 0, 0, 0.28)" onPress={handleClear} />
)}
</Pressable>

{showPicker && Platform.select({
android: (
<DateTimePicker
mode={mode}
value={selectedDate || new Date()}
minimumDate={minDate}
maximumDate={maxDate}
onChange={(event, date) => handleDateChange(date ?? selectedDate)}
/>
),
ios: (
<DateTimePickerModal
isVisible={showPicker}
mode={mode}
date={selectedDate || new Date()}
minimumDate={minDate}
maximumDate={maxDate}
onConfirm={handleDateChange}
onCancel={() => setShowPicker(false)}
/>
)
})}

{helperText && <Text style={styles.helperText}>{helperText}</Text>}
{show && (
<ReactDateTimePicker
mode={mode}
value={value || now}
minimumDate={minDate}
maximumDate={maxDate}
onChange={(event, date) => {
setShow(false)
if (event.type === 'set') {
setValue(date)
if (onChange) {
onChange(date)
}
}
}}
/>
)}
</View>
</View>
)
}

export default DateTimePicker
export default CustomDateTimePicker
14 changes: 14 additions & 0 deletions mobile/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"react-native-dotenv": "^3.4.11",
"react-native-feather": "^1.1.2",
"react-native-gesture-handler": "~2.20.2",
"react-native-modal-datetime-picker": "^18.0.0",
"react-native-paper": "^5.13.1",
"react-native-reanimated": "~3.16.7",
"react-native-safe-area-context": "4.12.0",
Expand Down

0 comments on commit 281d389

Please sign in to comment.