import React from 'react'; import { I18nManager, TextInput as Input, Modal, Text, ScrollView, TouchableOpacity, View, Image, Pressable } from 'react-native'; import styles from './styles'; import moment from 'jalali-moment'; import { months, weekDays } from '../utils/utils'; import { DatepickerProps } from './interfaces'; const Datepicker: React.FC = ({format = 'jYYYY/jMM/jDD', ...props}) => { const chevron = require('./chevron.png') // states const [open, setOpen] = React.useState(false) const [selectedDate, setSelectedDate] = React.useState('') const [day, setDay] = React.useState(moment().jDate()) const [monthIndex, setMonthIndex] = React.useState(moment().locale('fa').jMonth()) const [monthDays, setMonthDays] = React.useState>([]) const [month, setMonth] = React.useState(months()[monthIndex].label) const [monthView, setMonthView] = React.useState(false) const [year, setYear] = React.useState(moment().locale('fa').jYear()) const [yearsView, setYearsView] = React.useState(false) React.useLayoutEffect(() => { defaultConfigs() }, []) const defaultConfigs = () => { let dt = moment(`${year}/${monthIndex+1 > 10 ? monthIndex+1 : '0'+(monthIndex+1)}`, 'jYYYY/jMM').startOf('jMonth').weekday() let offsetDays = Array.from({length: weekDays()[dt + 1 >= 6 ? 0 : dt+1].value}, (v, i) => 0) let realDays = Array.from({length: moment.jDaysInMonth(year, monthIndex)}, (v, i) => i+1) let allDays: Array = weekDays()[dt + 1 >= 6 ? 0 : dt+1].value > 0 ? offsetDays.concat(realDays) : realDays setMonthDays(allDays) } // Open popup const openDatepicker = () => { setOpen(true) } // Close popup const closeDatepicker = () => { setYearsView(false) setMonthView(false) setOpen(false) } // Set data for last month const lastMonth = () => { let m = monthIndex > 0 ? monthIndex - 1 : 11 monthIndex === 0 && setYear(year-1) setMonthIndex(m) setMonth(months()[m].label) let dt = moment(`${monthIndex === 0 ? year-1 : year}/${m+1 >= 10 ? m+1 : '0'+(m+1)}`, 'jYYYY/jMM').startOf('jMonth').weekday() let offsetDays = Array.from({length: weekDays()[dt + 1 > 6 ? 0 : dt+1].value}, (v, i) => 0) let realDays = Array.from({length: moment.jDaysInMonth(monthIndex === 0 ? year-1 : year, m)}, (v, i) => i+1) let allDays: Array = offsetDays.concat(realDays) setMonthDays(allDays) } // Set data for next month const nextMonth = () => { let m = monthIndex < 11 ? monthIndex + 1 : 0 monthIndex === 11 && setYear(year+1) setMonthIndex(m) setMonth(months()[m].label) let dt = moment(`${monthIndex === 11 ? year + 1 : year}/${m+1 >= 10 ? m+1 : '0'+(m+1)}`, 'jYYYY/jMM').startOf('jMonth').weekday() let offsetDays = Array.from({length: weekDays()[dt+1 > 6 ? 0 : dt+1].value}, (v, i) => 0) let realDays = Array.from({length: moment.jDaysInMonth(monthIndex === 11 ? year + 1 : year, m)}, (v, i) => i+1) let allDays: Array = offsetDays.concat(realDays) setMonthDays(allDays) } const updateYear = (yearNm: number) => { setYear(yearNm) setMonth(months()[monthIndex].label) let dt = moment(`${yearNm}/${monthIndex >= 10 ? monthIndex : '0'+(monthIndex)}`, 'jYYYY/jMM').startOf('jMonth').weekday() let offsetDays = Array.from({length: weekDays()[dt+1 > 6 ? 0 : dt+1].value}, (v, i) => 0) let realDays = Array.from({length: moment.jDaysInMonth(yearNm, monthIndex+1)}, (v, i) => i+1) let allDays: Array = offsetDays.concat(realDays) setMonthDays(allDays) setYearsView(false) } const updateMonth = (monthNm: number) => { let m = months()[monthNm-1] setYear(year) setMonthIndex(m.value) setMonth(m.label) let dt = moment(`${year}/${m.value >= 10 ? m.value : '0'+(m.value)}`, 'jYYYY/jMM').startOf('jMonth').weekday() let offsetDays = Array.from({length: weekDays()[dt+1 > 6 ? 0 : dt+1].value}, (v, i) => 0) let realDays = Array.from({length: moment.jDaysInMonth(year, m.value)}, (v, i) => i+1) let allDays: Array = offsetDays.concat(realDays) setMonthDays(allDays) setMonthView(false) } /** * @description renders datepicker header section * */ const _renderDatepickerHeader = () => ( { props.backChevronIconComponent || } setMonthView(true)}> {month} setYearsView(true)}> {year} { props.nextChevronIconComponent || } ) const _renderDatepickerFooter = () => ( ) const setValue = () => { setSelectedDate(`${year} / ${monthIndex+1 >= 10 ? monthIndex+1 : '0'+(monthIndex+1) } / ${day >= 10 ? day : '0'+(day)}`) props.onChange && props.onChange(`${year}/${monthIndex+1 >= 10 ? monthIndex+1 : '0'+(monthIndex+1) }/${day >= 10 ? day : '0'+(day)}`) setOpen(false) } /** * @description closes datepicker without passing data */ const cancel = () => setOpen(false) /** * @description renders years view */ const _renderYears = React.useCallback( () => { return ( { Array.from({length: 100}, (v , i) => moment().jYear()-99+i).reverse().map((y, index) => { return updateYear(y)}> {y} }) } ) }, [] ) /** * @description Render month view */ const _renderMonths = React.useCallback( () => { return ( { months().map((m, index) => { return updateMonth(m.value)}> {m.label} }) } ) }, [month] ) return ( {/* input label */} { props.label && } {/* picker */} {}} editable={false} defaultValue={selectedDate} onChangeText={() => {}} /> {/* Years list view */} { yearsView && _renderYears() } {/* Months list view */} { monthView && _renderMonths() } {/* Calendar container */} { (!yearsView && !monthView) && {/* Header */} {_renderDatepickerHeader()} {/* Selected Date */} {`${day < 10 ? '0' + day : day} ${month} ${year}`} {/* Week Days */} { (props.weekDaysLables || weekDays()).map(weekDay => ( )) } {/* Body */} { monthDays.map((dayItem, index) => { return dayItem === day ? dayItem > 0 && setDay(dayItem)} /> : { year === moment().jYear() && monthIndex === moment().jMonth() && dayItem === moment().jDate() ? dayItem > 0 && setDay(dayItem)} /> : 0 ? 1 : 0}]} onPress={() => dayItem > 0 && setDay(dayItem)} /> } }) } {/* Footer */} {_renderDatepickerFooter()} } ) } export default Datepicker;