Skip to content

Commit

Permalink
feat(mobile): allow user select default currency (#160)
Browse files Browse the repository at this point in the history
Resolves #150
  • Loading branch information
bkdev98 committed Jul 23, 2024
1 parent 98bcbe9 commit f28f58a
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 127 deletions.
19 changes: 3 additions & 16 deletions apps/mobile/app/(app)/(tabs)/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Application from 'expo-application'
import { Logo } from '@/components/common/logo'
import { MenuItem } from '@/components/common/menu-item'
import { UserAvatar } from '@/components/common/user-avatar'
import { SelectDefaultCurrency } from '@/components/setting/select-default-currency'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Switch } from '@/components/ui/switch'
Expand All @@ -15,7 +16,6 @@ import { Link } from 'expo-router'
import {
BellIcon,
ChevronRightIcon,
CurrencyIcon,
EarthIcon,
GithubIcon,
InboxIcon,
Expand Down Expand Up @@ -124,28 +124,15 @@ export default function SettingsScreen() {
icon={EarthIcon}
rightSection={
<View className="flex flex-row items-center gap-2">
<Text className="text-muted-foreground font-sans">
<Text className="text-muted-foreground font-sans uppercase">
{t(i18n)`${language}`}
</Text>
<ChevronRightIcon className="w-5 h-5 text-primary" />
</View>
}
/>
</Link>
<Link href="/currency" asChild disabled>
<MenuItem
label={t(i18n)`Default currency`}
icon={CurrencyIcon}
rightSection={
<View className="flex flex-row items-center gap-2">
<Text className="text-muted-foreground font-sans">
{/* */}
</Text>
<ChevronRightIcon className="w-5 h-5 text-primary" />
</View>
}
/>
</Link>
<SelectDefaultCurrency />
<MenuItem
label={t(i18n)`Login using FaceID`}
icon={ScanFaceIcon}
Expand Down
4 changes: 3 additions & 1 deletion apps/mobile/app/(app)/transaction/new-record.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { TransactionForm } from '@/components/transaction/transaction-form'
import { createTransaction } from '@/mutations/transaction'
import { transactionQueries } from '@/queries/transaction'
import { useWallets, walletQueries } from '@/queries/wallet'
import { useDefaultCurrency } from '@/stores/user-settings/hooks'
import {
type TransactionFormValues,
zTransactionFormValues,
Expand All @@ -27,14 +28,15 @@ export default function NewRecordScreen() {
const queryClient = useQueryClient()
const router = useRouter()
const { data: walletAccounts } = useWallets()
const defaultCurrency = useDefaultCurrency()
const defaultWallet = walletAccounts?.[0]

const params = useLocalSearchParams()
const parsedParams = zUpdateTransaction.parse(params)
const defaultValues = {
date: new Date(),
amount: 0,
currency: 'USD',
currency: defaultCurrency,
note: '',
walletAccountId: defaultWallet?.id,
...parsedParams,
Expand Down
4 changes: 3 additions & 1 deletion apps/mobile/components/budget/budget-form.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useDefaultCurrency } from '@/stores/user-settings/hooks'
import {
type BudgetFormValues,
BudgetPeriodTypeSchema,
Expand Down Expand Up @@ -61,13 +62,14 @@ export const BudgetForm = ({
const { i18n } = useLingui()
const nameInputRef = useRef<TextInput>(null)
const amountInputRef = useRef<TextInput>(null)
const defaultCurrency = useDefaultCurrency()

const budgetForm = useForm<BudgetFormValues>({
resolver: zodResolver(zBudgetFormValues),
defaultValues: {
name: '',
description: '',
preferredCurrency: 'USD',
preferredCurrency: defaultCurrency,
type: BudgetTypeSchema.Enum.SPENDING,
...defaultValues,
period: {
Expand Down
10 changes: 8 additions & 2 deletions apps/mobile/components/budget/budget-statistic.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useDefaultCurrency } from '@/stores/user-settings/hooks'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import { View } from 'react-native'
Expand All @@ -13,13 +14,16 @@ export function BudgetStatistic({
remainingPerDay,
}: BudgetStatisticProps) {
const { i18n } = useLingui()
const defaultCurrency = useDefaultCurrency()

return (
<View className="flex-row items-center gap-6 justify-between">
<View className="gap-1">
<Text className="font-semibold text-2xl">
{totalRemaining?.toLocaleString() || '0.00'}{' '}
<Text className="text-muted-foreground font-normal text-sm">VND</Text>
<Text className="text-muted-foreground font-normal text-sm">
{defaultCurrency}
</Text>
</Text>
<Text className="text-muted-foreground">
{t(i18n)`Left this month`}
Expand All @@ -28,7 +32,9 @@ export function BudgetStatistic({
<View className="gap-1">
<Text className="font-semibold text-2xl text-right">
{remainingPerDay?.toLocaleString() || '0.00'}{' '}
<Text className="text-muted-foreground font-normal text-sm">VND</Text>
<Text className="text-muted-foreground font-normal text-sm">
{defaultCurrency}
</Text>
</Text>
<Text className="text-muted-foreground text-right">
{t(i18n)`Left per day`}
Expand Down
8 changes: 6 additions & 2 deletions apps/mobile/components/common/amount-format.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { cn } from '@/lib/utils'
import { useDefaultCurrency } from '@/stores/user-settings/hooks'
import { type VariantProps, cva } from 'class-variance-authority'
import { Text } from '../ui/text'

Expand Down Expand Up @@ -40,12 +41,13 @@ type AmountFormatProps = {

export function AmountFormat({
amount = 0,
currency = 'VND',
currency,
className,
size,
displayNegativeSign,
displayPositiveColor,
}: AmountFormatProps) {
const defaultCurrency = useDefaultCurrency()
return (
<Text
className={cn(
Expand All @@ -60,7 +62,9 @@ export function AmountFormat({
>
{(displayNegativeSign ? amount : Math.abs(amount)).toLocaleString() ||
'0.00'}{' '}
<Text className={cn(currencyVariants({ size }))}>{currency}</Text>
<Text className={cn(currencyVariants({ size }))}>
{currency || defaultCurrency}
</Text>
</Text>
)
}
72 changes: 72 additions & 0 deletions apps/mobile/components/setting/select-default-currency.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { BottomSheetBackdrop, BottomSheetModal } from '@gorhom/bottom-sheet'
import { useRef } from 'react'

import { useColorScheme } from '@/hooks/useColorScheme'
import { theme } from '@/lib/theme'
import { sleep } from '@/lib/utils'
import { useDefaultCurrency } from '@/stores/user-settings/hooks'
import { useUserSettingsStore } from '@/stores/user-settings/store'
import { t } from '@lingui/macro'
import { useLingui } from '@lingui/react'
import { ChevronRightIcon, CurrencyIcon } from 'lucide-react-native'
import { Keyboard, View } from 'react-native'
import { FullWindowOverlay } from 'react-native-screens'
import { CurrencySheetList } from '../common/currency-sheet'
import { MenuItem } from '../common/menu-item'
import { Text } from '../ui/text'

export function SelectDefaultCurrency() {
const { i18n } = useLingui()
const sheetRef = useRef<BottomSheetModal>(null)
const defaultCurrency = useDefaultCurrency()
const setPreferredCurrency = useUserSettingsStore().setPreferredCurrency
const { colorScheme } = useColorScheme()
return (
<>
<MenuItem
label={t(i18n)`Default currency`}
icon={CurrencyIcon}
onPress={() => {
Keyboard.dismiss()
sheetRef.current?.present()
}}
rightSection={
<View className="flex flex-row items-center gap-2">
<Text className="text-muted-foreground font-sans">
{defaultCurrency}
</Text>
<ChevronRightIcon className="w-5 h-5 text-primary" />
</View>
}
/>
<BottomSheetModal
ref={sheetRef}
index={0}
snapPoints={['50%', '87%']}
enablePanDownToClose
backgroundStyle={{ backgroundColor: theme[colorScheme].background }}
keyboardBehavior="extend"
backdropComponent={(props) => (
<BottomSheetBackdrop
{...props}
appearsOnIndex={0}
disappearsOnIndex={-1}
enableTouchThrough
/>
)}
containerComponent={(props) => (
<FullWindowOverlay>{props.children}</FullWindowOverlay>
)}
>
<CurrencySheetList
value={defaultCurrency}
onSelect={async (currency) => {
sheetRef.current?.close()
await sleep(500)
setPreferredCurrency?.(currency.code)
}}
/>
</BottomSheetModal>
</>
)
}
4 changes: 3 additions & 1 deletion apps/mobile/components/wallet/account-form.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useDefaultCurrency } from '@/stores/user-settings/hooks'
import { type AccountFormValues, zAccountFormValues } from '@6pm/validation'
import { zodResolver } from '@hookform/resolvers/zod'
import { t } from '@lingui/macro'
Expand All @@ -21,12 +22,13 @@ export const AccountForm = ({ onSubmit, defaultValues }: AccountFormProps) => {
const { i18n } = useLingui()
const nameInputRef = useRef<TextInput>(null)
const balanceInputRef = useRef<TextInput>(null)
const defaultCurrency = useDefaultCurrency()

const accountForm = useForm<AccountFormValues>({
resolver: zodResolver(zAccountFormValues),
defaultValues: {
name: '',
preferredCurrency: 'USD', // TODO: get from user settings
preferredCurrency: defaultCurrency,
icon: 'CreditCard',
...defaultValues,
},
Expand Down
Loading

0 comments on commit f28f58a

Please sign in to comment.