Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2808: Add a filter by date option to events #2898

Merged
merged 61 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
5028027
2808: Creating a component called CustomDatePicker and filtering even…
bahaaTuffaha Aug 20, 2024
b6683da
2808: Creating a hook for useDateFilter and a toggle to hide and show…
bahaaTuffaha Aug 21, 2024
8dd13b4
2808: web changes and adding translation and direction for RTL plus c…
bahaaTuffaha Aug 21, 2024
3fb9deb
2828: added a library called react-native-ui-datepicker and create Ca…
bahaaTuffaha Aug 22, 2024
566da43
2808: Added DateFilterToggle to native and improvements to useDateFil…
bahaaTuffaha Aug 24, 2024
3c0dbe5
2808: Adding translations and using React-native modal
bahaaTuffaha Aug 25, 2024
63d158a
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Aug 25, 2024
4df2415
2808: Replacing (react-native-ui-datepicker) with (react-native-calen…
bahaaTuffaha Aug 27, 2024
c67fd25
Added some tests and release note
bahaaTuffaha Aug 27, 2024
60f9de7
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Aug 27, 2024
193909c
2808: Refactoring code + some improvements
bahaaTuffaha Aug 27, 2024
e701023
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Aug 27, 2024
5d18825
2808: prettier:check fixed for tsconfig
bahaaTuffaha Aug 27, 2024
c1cab6d
2808: Fixing Typescript issues
bahaaTuffaha Aug 27, 2024
25406e8
2808: Requested changes about DateTime
bahaaTuffaha Aug 29, 2024
3321eb4
2808: Fix translations
steffenkleinle Sep 10, 2024
115de27
2808: Requested changes part 2
bahaaTuffaha Sep 11, 2024
e652e78
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Sep 11, 2024
000a9a4
2808: Requested changes part 3
bahaaTuffaha Sep 12, 2024
d7ca0ff
2808: Replacing names fromDate and toDate to startDate and endDate
bahaaTuffaha Sep 12, 2024
a6176f5
2808: Replacing alt with placeholder at date-input (web) for tests ge…
bahaaTuffaha Sep 13, 2024
5b10e03
2808: Requested changes Part4
bahaaTuffaha Sep 19, 2024
52db677
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Sep 19, 2024
8929238
2808: Dealing with recurrences and adding requested changes
bahaaTuffaha Oct 3, 2024
915c099
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Oct 3, 2024
a371455
2808: Fixing recurrence to show beyond the limit and some refactoring…
bahaaTuffaha Oct 13, 2024
df9e206
Merge branch 'main' into 2808-Add-a-filter-by-date-option-to-events
bahaaTuffaha Oct 13, 2024
075d88a
2808: Importing DateFilterUtils module properly
bahaaTuffaha Oct 13, 2024
87f7daa
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Oct 14, 2024
8ea2492
2808: Requested changes: general improvements
bahaaTuffaha Oct 16, 2024
ab81a63
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Oct 16, 2024
d537677
2808: Requested changes about moving focus to next input and improvin…
bahaaTuffaha Nov 1, 2024
2af2efa
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Nov 1, 2024
2464cc5
2808: Adding missing spaces
bahaaTuffaha Nov 1, 2024
a19bb07
2808: Modified CalendarRangeModal to let you select from or to date i…
bahaaTuffaha Nov 3, 2024
4232588
2808: small Refactoring
bahaaTuffaha Nov 4, 2024
f62a0ca
2808: Jumping backward when backspacing and Adding width for views ju…
bahaaTuffaha Nov 4, 2024
dc2a79f
2808: Expanded on some more tests for DatePicker spec file
bahaaTuffaha Nov 4, 2024
aeceee3
2808: Requested changes for DatePickers and adding more tests
bahaaTuffaha Nov 7, 2024
1f1ca05
2808: Added Accordion Animation for EventsDateFilter
bahaaTuffaha Nov 8, 2024
ac24b22
2808: Accordion changes and added invalidDate to translation
bahaaTuffaha Nov 11, 2024
20fd593
2808: Added Accordion Animation for EventsDateFilter
bahaaTuffaha Nov 8, 2024
829c7b2
Merge branch '2808-Add-a-filter-by-date-option-to-events' of https://…
bahaaTuffaha Nov 11, 2024
b3ba08b
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Nov 11, 2024
4282d93
2808: EventListItem can show the right date from the recurrences depe…
bahaaTuffaha Nov 20, 2024
abb3d98
2808: Fixing EventListItem test file
bahaaTuffaha Nov 20, 2024
4990e93
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Nov 20, 2024
2085834
2808: Adding tests for DateModal filterStartDate and filterEndDate pa…
bahaaTuffaha Nov 21, 2024
ca5a9bf
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Nov 21, 2024
0346272
2808: Changing placeholder for filter input at native
bahaaTuffaha Dec 2, 2024
c63fd9f
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Dec 2, 2024
09ee0ef
2808: Requested changes and improvements part1
bahaaTuffaha Dec 4, 2024
7a2b69b
2808: changing date input with react datepicker package
bahaaTuffaha Dec 9, 2024
ba14fa3
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Dec 9, 2024
672df15
2808: prettier fix
bahaaTuffaha Dec 9, 2024
4917393
2808: Fixing small overflow jumping issue
bahaaTuffaha Dec 9, 2024
e075d72
Merge remote-tracking branch 'origin' into 2808-Add-a-filter-by-date-…
bahaaTuffaha Dec 11, 2024
69f5ea5
2808: changing es2021 to es2022 for react-datepicker
bahaaTuffaha Dec 17, 2024
c197a85
Merge branch 'main' into 2808-Add-a-filter-by-date-option-to-events
bahaaTuffaha Jan 14, 2025
eda8b58
Fix CI
steffenkleinle Jan 20, 2025
d2d6b4e
Merge remote-tracking branch 'origin/main' into 2808-Add-a-filter-by-…
steffenkleinle Jan 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions native/src/components/CalendarRangeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ const DatePickerWrapper = styled.View`
position: absolute;
width: 90%;
top: 228px;
justify-self: center;
/* stylelint-disable-next-line declaration-block-no-redundant-longhand-properties */
align-self: center;
`
const StyledView = styled.View`
gap: 8px;
flex-direction: row;
justify-content: ${props => (props.theme.contentDirection === 'rtl' ? 'flex-start' : 'flex-end')};
flex-direction: ${props => (props.theme.contentDirection === 'ltr' ? 'row' : 'row-reverse')};
justify-content: flex-start;
padding: 5px 10px;
`
const StyledTextButton = styled(TextButton)`
Expand Down Expand Up @@ -63,14 +61,11 @@ const CalendarRangeModal = ({
const handleDayPress = (day: { dateString: string }) => {
const selectedDate = DateTime.fromISO(day.dateString)

if (!tempFromDate) {
if (!tempFromDate || tempToDate) {
setTempFromDate(selectedDate)
setTempToDate(null)
} else if (!tempToDate) {
setTempToDate(selectedDate)
} else {
setTempFromDate(selectedDate)
setTempToDate(null)
setTempToDate(selectedDate)
}
}

Expand All @@ -81,7 +76,7 @@ const CalendarRangeModal = ({
<Caption title={t('selectRange')} />
<Calendar
markingType='period'
markedDates={getMarkedDates(tempFromDate, tempToDate)}
markedDates={getMarkedDates(tempFromDate, tempToDate, theme)}
onDayPress={handleDayPress}
theme={{
calendarBackground: theme.colors.textDecorationColor,
Expand All @@ -104,13 +99,13 @@ const CalendarRangeModal = ({
/>
<StyledTextButton
onPress={() => {
if (Boolean(tempFromDate) && Boolean(tempToDate)) {
setFromDate(tempFromDate || DateTime.local())
setToDate(tempToDate || DateTime.local())
if (tempFromDate && tempToDate) {
setFromDate(tempFromDate)
setToDate(tempToDate)
}
closeModal()
}}
text={t('ok')}
text={t('common:ok')}
type='clear'
/>
</StyledView>
Expand Down
57 changes: 24 additions & 33 deletions native/src/components/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DateTime } from 'luxon'
import React, { ReactElement, useEffect, useState } from 'react'
import styled from 'styled-components/native'

import { DATE_FORMAT } from 'shared/constants'
import { DATE_FORMAT } from 'shared'

import { CalendarTodayIcon } from '../assets'
import Icon from './base/Icon'
Expand Down Expand Up @@ -57,35 +57,32 @@ const StyledError = styled.Text`
`
export type DatePickerProps = {
title: string
value: DateTime | null
setValue: (fromDate: DateTime | null) => void
date: DateTime | null
setDate: (date: DateTime | null) => void
error?: string
modalState: boolean
setModalState: React.Dispatch<React.SetStateAction<boolean>>
modalOpen: boolean
setModalOpen: (open: boolean) => void
}
const DatePicker = ({ title, value, setValue, error, modalState, setModalState }: DatePickerProps): ReactElement => {
const formatDate = (date: DateTime | null, part: number) => date?.toFormat(DATE_FORMAT).split('/')[part]

const [inputDay, setInputDay] = useState(formatDate(value, 0))
const [inputMonth, setInputMonth] = useState(formatDate(value, 1))
const [inputYear, setInputYear] = useState(formatDate(value, 2))
const DatePicker = ({ title, date, setDate, error, modalOpen, setModalOpen }: DatePickerProps): ReactElement => {
const [inputDay, setInputDay] = useState(date?.toFormat('dd'))
const [inputMonth, setInputMonth] = useState(date?.toFormat('MM'))
const [inputYear, setInputYear] = useState(date?.toFormat('yyyy'))

useEffect(() => {
try {
setValue(DateTime.fromFormat(`${inputDay}/${inputMonth}/${inputYear}`, DATE_FORMAT).toLocal())
setDate(DateTime.fromFormat(`${inputDay}/${inputMonth}/${inputYear}`, DATE_FORMAT))
} catch (e) {
setValue(null)
setDate(null)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [inputDay, inputMonth, inputYear])
}, [inputDay, inputMonth, inputYear, setDate])

useEffect(() => {
if (value) {
setInputDay(formatDate(value, 0))
setInputMonth(formatDate(value, 1))
setInputYear(formatDate(value, 2))
if (date) {
setInputDay(date.toFormat('dd'))
setInputMonth(date.toFormat('MM'))
setInputYear(date.toFormat('yyyy'))
}
}, [value])
}, [date])

return (
<DateContainer>
Expand All @@ -96,38 +93,32 @@ const DatePicker = ({ title, value, setValue, error, modalState, setModalState }
testID='DatePicker-day'
keyboardType='numeric'
maxLength={2}
onChangeText={event => {
setInputDay(event as string)
}}
onChangeText={setInputDay}
value={inputDay}
/>
<Text>/</Text>
<Text>.</Text>
<Input
testID='DatePicker-month'
keyboardType='numeric'
maxLength={2}
onChangeText={event => {
setInputMonth(event)
}}
onChangeText={setInputMonth}
value={inputMonth}
/>
<Text>/</Text>
<Text>.</Text>
<Input
testID='DatePicker-year'
maxLength={4}
keyboardType='numeric'
onChangeText={event => {
setInputYear(event)
}}
onChangeText={setInputYear}
value={inputYear}
/>
</Wrapper>
<StyledIconButton
$isModalOpen={modalState}
$isModalOpen={modalOpen}
icon={<Icon Icon={CalendarTodayIcon} />}
accessibilityLabel='calenderEventsIcon'
onPress={() => {
setModalState(true)
setModalOpen(true)
}}
/>
</StyledInputWrapper>
Expand Down
51 changes: 21 additions & 30 deletions native/src/components/EventsDateFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { TFunction } from 'i18next'
import { DateTime } from 'luxon'
import React, { useState } from 'react'
import { useTranslation } from 'react-i18next'
Expand Down Expand Up @@ -33,13 +32,11 @@ const StyledText = styled(Text)`
type ResetFilterTextProps = {
fromDate: DateTime | null
toDate: DateTime | null
defaultFromDate: DateTime | null
defaultToDate: DateTime | null
t: TFunction<'events', undefined>
}

const ResetFilterText = ({ fromDate, toDate, defaultFromDate, defaultToDate, t }: ResetFilterTextProps) => {
const title = `${t('resetFilter')} ${fromDate?.toFormat('dd/MM/yy') ?? defaultFromDate?.toFormat('dd/MM/yy')} - ${toDate?.toFormat('dd/MM/yy') ?? defaultToDate?.toFormat('dd/MM/yy')}`
const ResetFilterText = ({ fromDate, toDate }: ResetFilterTextProps) => {
const { t } = useTranslation('events')
const title = `${t('resetFilter')} ${fromDate?.toFormat('dd.MM.yy')} - ${toDate?.toFormat('dd.MM.yy')}`
return <StyledText>{title}</StyledText>
}

Expand All @@ -50,8 +47,8 @@ type EventsDateFilterProps = {
toDate: DateTime | null
setToDate: (fromDate: DateTime | null) => void
toDateError: string | null
modalState: boolean
setModalState: React.Dispatch<React.SetStateAction<boolean>>
modalOpen: boolean
setModalOpen: (modalOpen: boolean) => void
}
const EventsDateFilter = ({
fromDate,
Expand All @@ -60,35 +57,35 @@ const EventsDateFilter = ({
toDate,
setToDate,
toDateError,
modalState,
setModalState,
modalOpen,
setModalOpen,
}: EventsDateFilterProps): JSX.Element => {
const defaultFromDate = DateTime.local().startOf('day')
const defaultToDate = DateTime.local().plus({ day: 10 }).startOf('day')
const defaultFromDate = DateTime.now().startOf('day')
const defaultToDate = DateTime.now().plus({ day: 10 }).startOf('day')
const [toggleDateFilter, setToggleDateFilter] = useState(true)
const isReset = fromDate?.startOf('day').equals(defaultFromDate) && toDate?.startOf('day').equals(defaultToDate)
const { t } = useTranslation('events')
return (
<>
<DateSection>
<FilterToggle t={t} toggle={toggleDateFilter} setToggleDateFilter={setToggleDateFilter} />
<FilterToggle toggle={toggleDateFilter} setToggleDateFilter={setToggleDateFilter} />
{toggleDateFilter && (
<>
<DatePicker
modalState={modalState}
setModalState={setModalState}
setValue={setFromDate}
modalOpen={modalOpen}
setModalOpen={setModalOpen}
setDate={setFromDate}
title={t('from')}
error={(fromDateError as string) || ''}
value={fromDate}
error={t(fromDateError ?? '')}
date={fromDate}
/>
<DatePicker
modalState={modalState}
setModalState={setModalState}
setValue={setToDate}
modalOpen={modalOpen}
setModalOpen={setModalOpen}
setDate={setToDate}
title={t('to')}
error={(toDateError as string) || ''}
value={toDate}
error={t(toDateError ?? '')}
date={toDate}
/>
</>
)}
Expand All @@ -101,13 +98,7 @@ const EventsDateFilter = ({
setToDate(defaultToDate)
}}>
<Icon Icon={CloseIcon} />
<ResetFilterText
fromDate={fromDate}
toDate={toDate}
t={t}
defaultFromDate={defaultFromDate}
defaultToDate={defaultToDate}
/>
<ResetFilterText fromDate={fromDate ?? defaultFromDate} toDate={toDate ?? defaultToDate} />
</StyledButton>
)}
</>
Expand Down
18 changes: 10 additions & 8 deletions native/src/components/FilterToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TFunction } from 'i18next'
import React, { ReactElement } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components/native'

import { ExpandIcon, ShrinkIcon } from '../assets'
Expand All @@ -21,13 +21,15 @@ const StyledButton = styled.TouchableOpacity`
type DateFilterToggleProps = {
toggle: boolean
setToggleDateFilter: React.Dispatch<React.SetStateAction<boolean>>
t: TFunction<'events', undefined>
}

const FilterToggle = ({ toggle, setToggleDateFilter, t }: DateFilterToggleProps): ReactElement => (
<StyledButton onPress={() => setToggleDateFilter((prev: boolean) => !prev)}>
<Icon Icon={toggle ? ShrinkIcon : ExpandIcon} />
{toggle ? <StyledText>{t('hideFilters')}</StyledText> : <StyledText>{t('showFilters')}</StyledText>}
</StyledButton>
)
const FilterToggle = ({ toggle, setToggleDateFilter }: DateFilterToggleProps): ReactElement => {
const { t } = useTranslation('events')
return (
<StyledButton onPress={() => setToggleDateFilter((prev: boolean) => !prev)}>
<Icon Icon={toggle ? ShrinkIcon : ExpandIcon} />
<StyledText>{t(toggle ? 'hideFilters' : 'showFilters')}</StyledText>
</StyledButton>
)
}
export default FilterToggle
21 changes: 5 additions & 16 deletions native/src/components/__tests__/CalendarRangeModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,7 @@ import React from 'react'
import renderWithTheme from '../../testing/render'
import CalendarRangeModal from '../CalendarRangeModal'

jest.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => {
const translations: Record<string, string> = {
'layout:cancel': 'Cancel',
ok: 'OK',
selectRange: 'Select Date Range',
}
return translations[key] || key
},
}),
}))
jest.mock('react-i18next')

describe('CalendarRangeModal', () => {
beforeEach(jest.clearAllMocks)
Expand All @@ -29,25 +18,25 @@ describe('CalendarRangeModal', () => {
renderWithTheme(
<CalendarRangeModal
closeModal={closeModal}
fromDate={DateTime.local()}
fromDate={DateTime.now()}
modalVisible
setFromDate={setFromDate}
setToDate={setToDate}
toDate={DateTime.local().plus({ day: 2 })}
toDate={DateTime.now().plus({ day: 2 })}
/>,
)

it('should close modal on "Cancel" button press', () => {
const { getByText } = renderCalendarRangeModal()

fireEvent.press(getByText('Cancel'))
fireEvent.press(getByText('layout:cancel'))
expect(closeModal).toHaveBeenCalledTimes(1)
})

it('should set dates and close modal on "OK" button press', () => {
const { getByText } = renderCalendarRangeModal()

fireEvent.press(getByText('OK'))
fireEvent.press(getByText('common:ok'))
expect(setFromDate).toHaveBeenCalled()
expect(setToDate).toHaveBeenCalled()
expect(closeModal).toHaveBeenCalledTimes(1)
Expand Down
Loading
Loading