Skip to content

Commit

Permalink
feat(mobile): [Transaction] add select date field
Browse files Browse the repository at this point in the history
  • Loading branch information
Quốc Khánh committed Jul 10, 2024
1 parent cd4f517 commit 31a14da
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 8 deletions.
112 changes: 112 additions & 0 deletions apps/mobile/components/transaction/select-date-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { formatDateShort } from '@/lib/date'
import { sleep } from '@/lib/utils'
import {
BottomSheetBackdrop,
BottomSheetModal,
BottomSheetView,
} from '@gorhom/bottom-sheet'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import DateTimePicker from '@react-native-community/datetimepicker'
import { Calendar } from 'lucide-react-native'
import { useRef, useState } from 'react'
import { useController } from 'react-hook-form'
import { View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { FullWindowOverlay } from 'react-native-screens'
import { Button } from '../ui/button'
import { Text } from '../ui/text'

function SpinnerDatePicker({
value,
onChange,
}: {
value: Date
onChange: (date: Date | undefined) => void
}) {
const { i18n } = useLingui()
const [date, setDate] = useState<Date | undefined>(value)

return (
<View className="gap-4">
<DateTimePicker
value={value}
mode="date"
display="spinner"
onChange={(_, selectedDate) => {
setDate(selectedDate)
}}
/>
<Button
className="mx-6"
onPress={() => {
onChange(date)
}}
>
<Text>{t(i18n)`Save`}</Text>
</Button>
</View>
)
}

export function SelectDateField({
onSelect,
}: {
onSelect?: (date?: Date) => void
}) {
const { bottom } = useSafeAreaInsets()
const sheetRef = useRef<BottomSheetModal>(null)
const {
field: { onChange, onBlur, value },
} = useController({ name: 'date' })

return (
<>
<Button
variant="outline"
className="!px-3"
onPress={() => {
sheetRef.current?.present()
}}
>
<Calendar className="w-5 h-5 text-primary" />
<Text>{formatDateShort(value)}</Text>
</Button>
<BottomSheetModal
ref={sheetRef}
index={0}
enableDynamicSizing
enablePanDownToClose
keyboardBehavior="extend"
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
<BottomSheetView
style={{
paddingBottom: bottom,
}}
>
<SpinnerDatePicker
value={value}
onChange={async (date) => {
sheetRef.current?.close()
await sleep(500)
onChange(date)
onBlur()
onSelect?.(date)
}}
/>
</BottomSheetView>
</BottomSheetModal>
</>
)
}
8 changes: 3 additions & 5 deletions apps/mobile/components/transaction/transaction-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { zodResolver } from '@hookform/resolvers/zod'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import { Calendar, LandPlot, XIcon } from 'lucide-react-native'
import { LandPlot, XIcon } from 'lucide-react-native'
import { Controller, FormProvider, useForm } from 'react-hook-form'
import { ScrollView, View } from 'react-native'
import Animated, {
Expand All @@ -20,6 +20,7 @@ import { Button } from '../ui/button'
import { Text } from '../ui/text'
import { SelectAccountField } from './select-account-field'
import { SelectCategoryField } from './select-category-field'
import { SelectDateField } from './select-date-field'

type TransactionFormProps = {
onSubmit: (data: TransactionFormValues) => void
Expand Down Expand Up @@ -63,10 +64,7 @@ export const TransactionForm = ({
contentContainerClassName="flex-1 justify-between bg-muted"
>
<View className="flex-row justify-between items-center p-6 pb-0">
<Button variant="outline" className="!px-3">
<Calendar className="w-5 h-5 text-primary" />
<Text>Today</Text>
</Button>
<SelectDateField />
<Button size="icon" variant="secondary" onPress={onCancel}>
<XIcon className="size-6 text-primary" />
</Button>
Expand Down
26 changes: 26 additions & 0 deletions apps/mobile/lib/date.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { t } from '@lingui/macro'
import { format } from 'date-fns/format'
import { isSameYear } from 'date-fns/isSameYear'
import { isToday } from 'date-fns/isToday'
import { isTomorrow } from 'date-fns/isTomorrow'
import { isYesterday } from 'date-fns/isYesterday'

export function formatDateShort(date: Date) {
if (isToday(date)) {
return t`Today`
}

if (isYesterday(date)) {
return t`Yesterday`
}

if (isTomorrow(date)) {
return t`Tomorrow`
}

if (isSameYear(date, new Date())) {
return format(date, 'MMM d')
}

return format(date, 'P')
}
2 changes: 2 additions & 0 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-community/datetimepicker": "8.0.1",
"@react-navigation/native": "^6.0.2",
"@tanstack/react-query": "^5.40.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"date-fns": "^3.6.0",
"expo": "~51.0.11",
"expo-auth-session": "~5.5.2",
"expo-constants": "~16.0.2",
Expand Down
28 changes: 25 additions & 3 deletions pnpm-lock.yaml

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

0 comments on commit 31a14da

Please sign in to comment.