From 7b7d87fc03ab808b3ce3ea0839c5d122eb274668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Kh=C3=A1nh?= Date: Sun, 1 Sep 2024 20:24:27 +0700 Subject: [PATCH] feat(mobile): add user default budget (#248) ![Simulator Screenshot - iPhone 15 Pro - 2024-09-01 at 19.49.33.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/1VEKR8FQ1Qa5iAiqVGqF/15c861e9-ae4c-4314-bbd3-0ed275f1a83c.png) --- apps/mobile/app/(app)/_layout.tsx | 6 +- .../app/(app)/budget/[budgetId]/edit.tsx | 8 ++- apps/mobile/app/(app)/budget/new-budget.tsx | 12 +++- .../app/(app)/transaction/new-record.tsx | 3 + apps/mobile/app/onboarding/step-two.tsx | 11 ++-- apps/mobile/components/budget/budget-form.tsx | 3 + apps/mobile/components/budget/budget-item.tsx | 13 ++++- .../components/form-fields/boolean-field.tsx | 52 +++++++++++++++++ apps/mobile/components/ui/switch.tsx | 16 +++--- apps/mobile/hooks/use-user-metadata.tsx | 30 ++++++++++ apps/mobile/locales/en/messages.po | 56 +++++++++++-------- apps/mobile/locales/en/messages.ts | 2 +- apps/mobile/locales/vi/messages.po | 56 +++++++++++-------- apps/mobile/locales/vi/messages.ts | 2 +- apps/mobile/package.json | 1 + packages/validation/src/budget.zod.ts | 2 + pnpm-lock.yaml | 29 ++++++++++ 17 files changed, 230 insertions(+), 72 deletions(-) create mode 100644 apps/mobile/components/form-fields/boolean-field.tsx create mode 100644 apps/mobile/hooks/use-user-metadata.tsx diff --git a/apps/mobile/app/(app)/_layout.tsx b/apps/mobile/app/(app)/_layout.tsx index 9d978647..ca89ac0a 100644 --- a/apps/mobile/app/(app)/_layout.tsx +++ b/apps/mobile/app/(app)/_layout.tsx @@ -3,6 +3,7 @@ import { BackButton } from '@/components/common/back-button' import { Button } from '@/components/ui/button' import { useLocalAuth } from '@/hooks/use-local-auth' import { useScheduleNotificationTrigger } from '@/hooks/use-schedule-notification' +import { useUserMetadata } from '@/hooks/use-user-metadata' import { useColorScheme } from '@/hooks/useColorScheme' import { theme } from '@/lib/theme' import { useUser } from '@clerk/clerk-expo' @@ -13,7 +14,8 @@ import { PlusIcon } from 'lucide-react-native' import { useEffect } from 'react' export default function AuthenticatedLayout() { - const { user, isLoaded, isSignedIn } = useUser() + const { isLoaded, isSignedIn } = useUser() + const { onboardedAt } = useUserMetadata() const { colorScheme } = useColorScheme() const { i18n } = useLingui() const { shouldAuthLocal, setShouldAuthLocal } = useLocalAuth() @@ -29,7 +31,7 @@ export default function AuthenticatedLayout() { return } - if (!user?.unsafeMetadata?.onboardedAt && isLoaded) { + if (!onboardedAt && isLoaded) { return } diff --git a/apps/mobile/app/(app)/budget/[budgetId]/edit.tsx b/apps/mobile/app/(app)/budget/[budgetId]/edit.tsx index 55ef458e..5e31013d 100644 --- a/apps/mobile/app/(app)/budget/[budgetId]/edit.tsx +++ b/apps/mobile/app/(app)/budget/[budgetId]/edit.tsx @@ -1,5 +1,6 @@ import { BudgetForm } from '@/components/budget/budget-form' import { Button } from '@/components/ui/button' +import { useUserMetadata } from '@/hooks/use-user-metadata' import { useBudget, useDeleteBudget, @@ -23,6 +24,7 @@ export default function EditBudgetScreen() { const { budget } = useBudget(budgetId!) const { mutateAsync } = useUpdateBudget() const { mutateAsync: mutateDelete } = useDeleteBudget() + const { setDefaultBudgetId, defaultBudgetId } = useUserMetadata() const { sideOffset, ...rootProps } = useModalPortalRoot() useEffect(() => { @@ -65,7 +67,10 @@ export default function EditBudgetScreen() { orderBy(budget?.periodConfigs, 'startDate', 'desc'), ) - const handleUpdate = async (data: BudgetFormValues) => { + const handleUpdate = async ({ isDefault, ...data }: BudgetFormValues) => { + if (isDefault) { + await setDefaultBudgetId(budget?.id) + } mutateAsync({ data: data, id: budget?.id!, @@ -95,6 +100,7 @@ export default function EditBudgetScreen() { startDate: latestPeriodConfig?.startDate ?? undefined, endDate: latestPeriodConfig?.endDate ?? undefined, }, + isDefault: defaultBudgetId === budget?.id, }} /> diff --git a/apps/mobile/app/(app)/budget/new-budget.tsx b/apps/mobile/app/(app)/budget/new-budget.tsx index 74ab7522..ba106cbf 100644 --- a/apps/mobile/app/(app)/budget/new-budget.tsx +++ b/apps/mobile/app/(app)/budget/new-budget.tsx @@ -1,4 +1,5 @@ import { BudgetForm } from '@/components/budget/budget-form' +import { useUserMetadata } from '@/hooks/use-user-metadata' import { useCreateBudget } from '@/stores/budget/hooks' import type { BudgetFormValues } from '@6pm/validation' import { createId } from '@paralleldrive/cuid2' @@ -6,12 +7,19 @@ import { PortalHost, useModalPortalRoot } from '@rn-primitives/portal' import { useRouter } from 'expo-router' import { View } from 'react-native' +const budgetId = createId() + export default function CreateBudgetScreen() { const router = useRouter() const { mutateAsync } = useCreateBudget() const { sideOffset, ...rootProps } = useModalPortalRoot() + const { setDefaultBudgetId } = useUserMetadata() + + const handleCreate = async ({ isDefault, ...data }: BudgetFormValues) => { + if (isDefault) { + await setDefaultBudgetId(budgetId) + } - const handleCreate = async (data: BudgetFormValues) => { mutateAsync({ data: { ...data, @@ -20,7 +28,7 @@ export default function CreateBudgetScreen() { id: createId(), }, }, - id: createId(), + id: budgetId, }).catch(() => { // ignore }) diff --git a/apps/mobile/app/(app)/transaction/new-record.tsx b/apps/mobile/app/(app)/transaction/new-record.tsx index fbf9459a..2d42f551 100644 --- a/apps/mobile/app/(app)/transaction/new-record.tsx +++ b/apps/mobile/app/(app)/transaction/new-record.tsx @@ -1,6 +1,7 @@ import { toast } from '@/components/common/toast' import { Scanner } from '@/components/transaction/scanner' import { TransactionForm } from '@/components/transaction/transaction-form' +import { useUserMetadata } from '@/hooks/use-user-metadata' import { useWallets, walletQueries } from '@/queries/wallet' import { useCreateTransaction } from '@/stores/transaction/hooks' import { useDefaultCurrency } from '@/stores/user-settings/hooks' @@ -32,6 +33,7 @@ export default function NewRecordScreen() { const defaultWallet = walletAccounts?.[0] const { sideOffset, ...rootProps } = useModalPortalRoot() const [page, setPage] = useState(0) + const { defaultBudgetId } = useUserMetadata() const params = useLocalSearchParams() const parsedParams = zUpdateTransaction.parse(params) @@ -41,6 +43,7 @@ export default function NewRecordScreen() { currency: defaultCurrency, note: '', walletAccountId: defaultWallet?.id, + budgetId: defaultBudgetId as string, ...parsedParams, } diff --git a/apps/mobile/app/onboarding/step-two.tsx b/apps/mobile/app/onboarding/step-two.tsx index 0a18c4d9..db643a04 100644 --- a/apps/mobile/app/onboarding/step-two.tsx +++ b/apps/mobile/app/onboarding/step-two.tsx @@ -2,10 +2,10 @@ import { SubmitButton } from '@/components/form-fields/submit-button' import { NumericPad } from '@/components/numeric-pad' import { TransactionAmount } from '@/components/transaction/transaction-form' import { Text } from '@/components/ui/text' +import { useUserMetadata } from '@/hooks/use-user-metadata' import { useCreateBudget } from '@/stores/budget/hooks' import { useDefaultCurrency } from '@/stores/user-settings/hooks' import { BudgetPeriodTypeSchema, BudgetTypeSchema } from '@6pm/validation' -import { useUser } from '@clerk/clerk-expo' import { zodResolver } from '@hookform/resolvers/zod' import { t } from '@lingui/macro' import { useLingui } from '@lingui/react' @@ -59,7 +59,7 @@ export default function StepTwoScreen() { const { i18n } = useLingui() const defaultCurrency = useDefaultCurrency() const { mutateAsync } = useCreateBudget() - const { user } = useUser() + const { setOnboardedAt, setDefaultBudgetId } = useUserMetadata() const router = useRouter() const form = useForm({ @@ -88,11 +88,8 @@ export default function StepTwoScreen() { // ignore }) - await user?.update({ - unsafeMetadata: { - onboardedAt: new Date().toISOString(), - }, - }) + await setDefaultBudgetId(budgetId) + await setOnboardedAt(new Date().toISOString()) const { status: existingStatus } = await Notifications.getPermissionsAsync() diff --git a/apps/mobile/components/budget/budget-form.tsx b/apps/mobile/components/budget/budget-form.tsx index fdd5635b..0564cbeb 100644 --- a/apps/mobile/components/budget/budget-form.tsx +++ b/apps/mobile/components/budget/budget-form.tsx @@ -19,6 +19,7 @@ import { } from 'react-hook-form' import { ScrollView } from 'react-native' import type { TextInput } from 'react-native' +import { BooleanField } from '../form-fields/boolean-field' import { CurrencyField } from '../form-fields/currency-field' import { InputField } from '../form-fields/input-field' import { SubmitButton } from '../form-fields/submit-button' @@ -157,6 +158,8 @@ export const BudgetForm = ({ + + diff --git a/apps/mobile/components/budget/budget-item.tsx b/apps/mobile/components/budget/budget-item.tsx index 59450f35..d5006ee5 100644 --- a/apps/mobile/components/budget/budget-item.tsx +++ b/apps/mobile/components/budget/budget-item.tsx @@ -4,6 +4,7 @@ import { Link } from 'expo-router' import type { FC } from 'react' import { Pressable, View } from 'react-native' +import { useUserMetadata } from '@/hooks/use-user-metadata' import { getLatestPeriodConfig, useBudgetPeriodStats, @@ -25,6 +26,7 @@ type BudgetItemProps = { export const BudgetItem: FC = ({ budget }) => { const { i18n } = useLingui() const { user } = useUser() + const { defaultBudgetId } = useUserMetadata() const latestPeriodConfig = getLatestPeriodConfig(budget.periodConfigs) @@ -36,6 +38,8 @@ export const BudgetItem: FC = ({ budget }) => { isExceeded, } = useBudgetPeriodStats(latestPeriodConfig!) + const isDefault = defaultBudgetId === budget.id + return ( = ({ budget }) => { > - + = ({ budget }) => { className="h-7 w-7" fallbackLabelClassName="text-[10px]" /> - + {isDefault && ( + + {t(i18n)`Default`} + + )} + {latestPeriodConfig?.type} diff --git a/apps/mobile/components/form-fields/boolean-field.tsx b/apps/mobile/components/form-fields/boolean-field.tsx new file mode 100644 index 00000000..18587094 --- /dev/null +++ b/apps/mobile/components/form-fields/boolean-field.tsx @@ -0,0 +1,52 @@ +import { cn } from '@/lib/utils' +import { useController } from 'react-hook-form' +import { Text, View } from 'react-native' +import { Label } from '../ui/label' +import { Switch } from '../ui/switch' + +type BooleanFieldProps = { + name: string + label?: string + disabled?: boolean + wrapperClassName?: string + className?: string +} + +export const BooleanField = ({ + name, + label, + className, + wrapperClassName, + disabled, +}: BooleanFieldProps) => { + const { + field: { onChange, value }, + fieldState, + } = useController({ name }) + return ( + + + {!!label && ( + + )} + + + {!!fieldState.error && ( + {fieldState.error.message} + )} + + ) +} diff --git a/apps/mobile/components/ui/switch.tsx b/apps/mobile/components/ui/switch.tsx index 8d651f89..9bf54f16 100644 --- a/apps/mobile/components/ui/switch.tsx +++ b/apps/mobile/components/ui/switch.tsx @@ -1,4 +1,6 @@ -import * as SwitchPrimitives from '@/components/primitives/switch' +import { useColorScheme } from '@/hooks/useColorScheme' +import { cn } from '@/lib/utils' +import * as SwitchPrimitives from '@rn-primitives/switch' import * as React from 'react' import { Platform } from 'react-native' import Animated, { @@ -8,16 +10,13 @@ import Animated, { withTiming, } from 'react-native-reanimated' -import { useColorScheme } from '@/hooks/useColorScheme' -import { cn } from '@/lib/utils' - const SwitchWeb = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( diff --git a/apps/mobile/hooks/use-user-metadata.tsx b/apps/mobile/hooks/use-user-metadata.tsx new file mode 100644 index 00000000..61cfa139 --- /dev/null +++ b/apps/mobile/hooks/use-user-metadata.tsx @@ -0,0 +1,30 @@ +import { useUser } from '@clerk/clerk-expo' + +export function useUserMetadata() { + const { user } = useUser() + + async function setOnboardedAt(onboardedAt: string | undefined) { + return user?.update({ + unsafeMetadata: { + ...(user?.unsafeMetadata ?? {}), + onboardedAt, + }, + }) + } + + async function setDefaultBudgetId(defaultBudgetId: string | undefined) { + return user?.update({ + unsafeMetadata: { + ...(user?.unsafeMetadata ?? {}), + defaultBudgetId, + }, + }) + } + + return { + onboardedAt: user?.unsafeMetadata?.onboardedAt, + defaultBudgetId: user?.unsafeMetadata?.defaultBudgetId, + setOnboardedAt, + setDefaultBudgetId, + } +} diff --git a/apps/mobile/locales/en/messages.po b/apps/mobile/locales/en/messages.po index 5b4e9d6a..8ec82b74 100644 --- a/apps/mobile/locales/en/messages.po +++ b/apps/mobile/locales/en/messages.po @@ -25,11 +25,11 @@ msgstr "" msgid "{language}" msgstr "" -#: apps/mobile/components/budget/budget-item.tsx:90 +#: apps/mobile/components/budget/budget-item.tsx:99 msgid "{remainingDays} days left" msgstr "" -#: apps/mobile/app/onboarding/step-two.tsx:127 +#: apps/mobile/app/onboarding/step-two.tsx:124 msgid "* you can always change this later." msgstr "" @@ -45,7 +45,7 @@ msgstr "" #~ msgid "<0>By continuing, you acknowledge that you understand and agree to the <1><2>Terms & Conditions and <3><4>Privacy Policy" #~ msgstr "" -#: apps/mobile/components/budget/budget-form.tsx:120 +#: apps/mobile/components/budget/budget-form.tsx:121 #: apps/mobile/components/wallet/account-form.tsx:86 msgid "0.00" msgstr "" @@ -104,12 +104,12 @@ msgstr "" msgid "App theme" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:94 +#: apps/mobile/app/(app)/_layout.tsx:96 #: apps/mobile/app/(app)/(tabs)/settings.tsx:131 msgid "Appearance" msgstr "" -#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:37 +#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:39 msgid "Are you sure you want to delete this budget? This action cannot be undone." msgstr "" @@ -158,7 +158,7 @@ msgid "Camera permissions are not granted" msgstr "" #: apps/mobile/app/(app)/(tabs)/settings.tsx:248 -#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:43 +#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:45 #: apps/mobile/app/(app)/profile.tsx:120 #: apps/mobile/app/(app)/transaction/[transactionId].tsx:77 #: apps/mobile/app/(app)/wallet/[walletId].tsx:77 @@ -169,7 +169,7 @@ msgstr "" msgid "Cannot extract transaction data" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:126 +#: apps/mobile/app/(app)/_layout.tsx:128 #: apps/mobile/app/(app)/(tabs)/settings.tsx:104 msgid "Categories" msgstr "" @@ -223,11 +223,15 @@ msgstr "" msgid "Debt" msgstr "" +#: apps/mobile/components/budget/budget-item.tsx:69 +msgid "Default" +msgstr "" + #: apps/mobile/components/setting/select-default-currency.tsx:23 msgid "Default currency" msgstr "" -#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:47 +#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:49 #: apps/mobile/app/(app)/profile.tsx:124 #: apps/mobile/app/(app)/transaction/[transactionId].tsx:81 #: apps/mobile/app/(app)/wallet/[walletId].tsx:81 @@ -246,11 +250,11 @@ msgstr "" msgid "Display name" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:120 +#: apps/mobile/app/(app)/_layout.tsx:122 msgid "Edit account" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:147 +#: apps/mobile/app/(app)/_layout.tsx:149 msgid "Edit category" msgstr "" @@ -291,7 +295,7 @@ msgstr "" msgid "Expenses" msgstr "" -#: apps/mobile/components/budget/budget-form.tsx:111 +#: apps/mobile/components/budget/budget-form.tsx:112 msgid "Family budget" msgstr "" @@ -315,7 +319,7 @@ msgstr "" msgid "Grant camera permissions" msgstr "" -#: apps/mobile/app/onboarding/step-two.tsx:119 +#: apps/mobile/app/onboarding/step-two.tsx:116 msgid "If you're not sure, start with how much you usually spend per month." msgstr "" @@ -336,7 +340,7 @@ msgstr "" msgid "Keeping up with your spending and budgets." msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:82 +#: apps/mobile/app/(app)/_layout.tsx:84 #: apps/mobile/app/(app)/(tabs)/settings.tsx:140 msgid "Language" msgstr "" @@ -369,7 +373,7 @@ msgstr "" msgid "Monthly budget" msgstr "" -#: apps/mobile/components/budget/budget-form.tsx:110 +#: apps/mobile/components/budget/budget-form.tsx:111 #: apps/mobile/components/category/category-form.tsx:66 #: apps/mobile/components/wallet/account-form.tsx:69 msgid "Name" @@ -387,17 +391,17 @@ msgstr "" msgid "New {0}" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:113 +#: apps/mobile/app/(app)/_layout.tsx:115 #: apps/mobile/app/(app)/wallet/accounts.tsx:26 msgid "New account" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:154 +#: apps/mobile/app/(app)/_layout.tsx:156 #: apps/mobile/app/(app)/(tabs)/_layout.tsx:80 msgid "New budget" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:140 +#: apps/mobile/app/(app)/_layout.tsx:142 msgid "New category" msgstr "" @@ -417,7 +421,7 @@ msgstr "" msgid "Others" msgstr "" -#: apps/mobile/components/budget/budget-item.tsx:103 +#: apps/mobile/components/budget/budget-item.tsx:112 msgid "per day" msgstr "" @@ -449,7 +453,7 @@ msgstr "" msgid "Processing transaction..." msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:89 +#: apps/mobile/app/(app)/_layout.tsx:91 msgid "Profile" msgstr "" @@ -493,7 +497,7 @@ msgstr "" msgid "Revenue this week" msgstr "" -#: apps/mobile/components/budget/budget-form.tsx:50 +#: apps/mobile/components/budget/budget-form.tsx:51 #: apps/mobile/components/category/category-form.tsx:118 #: apps/mobile/components/common/date-picker.tsx:49 #: apps/mobile/components/common/date-range-picker.tsx:56 @@ -543,6 +547,10 @@ msgstr "" msgid "Send feedback" msgstr "" +#: apps/mobile/components/budget/budget-form.tsx:161 +msgid "Set as default" +msgstr "" + #: apps/mobile/app/onboarding/step-two.tsx:50 msgid "Set Budget" msgstr "" @@ -551,7 +559,7 @@ msgstr "" msgid "Set Monthly Budget" msgstr "" -#: apps/mobile/app/onboarding/step-two.tsx:116 +#: apps/mobile/app/onboarding/step-two.tsx:113 msgid "Set your monthly spending goal" msgstr "" @@ -617,7 +625,7 @@ msgstr "" msgid "Take a picture of your transaction" msgstr "" -#: apps/mobile/components/budget/budget-form.tsx:119 +#: apps/mobile/components/budget/budget-form.tsx:120 msgid "Target" msgstr "" @@ -649,7 +657,7 @@ msgstr "" msgid "Tomorrow" msgstr "" -#: apps/mobile/app/(app)/transaction/new-record.tsx:58 +#: apps/mobile/app/(app)/transaction/new-record.tsx:61 msgid "Transaction created" msgstr "" @@ -705,7 +713,7 @@ msgstr "" msgid "Wallet account name" msgstr "" -#: apps/mobile/app/(app)/_layout.tsx:99 +#: apps/mobile/app/(app)/_layout.tsx:101 #: apps/mobile/app/(app)/(tabs)/settings.tsx:95 msgid "Wallet accounts" msgstr "" diff --git a/apps/mobile/locales/en/messages.ts b/apps/mobile/locales/en/messages.ts index bf860c5f..ac72f7ca 100644 --- a/apps/mobile/locales/en/messages.ts +++ b/apps/mobile/locales/en/messages.ts @@ -1,4 +1,4 @@ /*eslint-disable*/ import type { Messages } from '@lingui/core' export const messages = JSON.parse( - '{"J/hVSQ":[["0"]],"6MIiOI":[["0"]," left"],"FEZKSz":[["language"]],"4E30de":[["remainingDays"]," days left"],"GDr6hQ":"* you can always change this later.","VE5ikN":"<0><1>Manage your expense seamlessly<2>Let <3>6pm a good time to spend","ejSd6i":"<0>By continuing, you acknowledge that you understand and agree to our <1><2>Privacy Policy","AYTmQ1":"<0>By continuing, you acknowledge that you understand and agree to the <1><2>Terms & Conditions and <3><4>Privacy Policy","LjsgKU":"0.00","y+OdTP":"Account deleted successfully","103Xyi":"Add your first transaction here","sxkWRg":"Advanced","Mxjwaz":"All accounts","pXc4dB":"All Accounts","HoJ+ka":"All entries","LcouyV":"All your data will be deleted","Vw8l6h":"An error occurred","bhrKSa":"An error occurred while deleting the transaction","rBd1BM":"An error occurred while updating the transaction","+FI+0t":"App is locked. Please authenticate to continue.","2Yw5Eq":"App settings","rg8lHb":"App theme","aAIQg2":"Appearance","rH4FJH":"Are you sure you want to delete this budget? This action cannot be undone.","TE1tui":"Are you sure you want to delete your account? This action cannot be undone.","apLLSU":"Are you sure you want to sign out?","6foA8n":"Are you sure?","X2pgJW":"Ask AI anything...","kfcRb0":"Avatar","fsBGk0":"Balance","IGsZpB":"Budgets","HjGOT5":"By day","kYFORZ":"By month","OTL6lf":"By week","HjYcC9":"Camera permissions are not granted","dEgA5A":"Cancel","dZYaqU":"Cannot extract transaction data","NUrY9o":"Categories","i+de8A":"Category name","h4wXn9":"Choose a preferred theme for the 6pm","AUYALh":"Coming soon","xGVfLh":"Continue","RvVi9c":"Continue with Email","eGKI3t":"Copied version to clipboard","PxMcud":"Current balance","AJToWu":"Current state","7cFjHo":"Daily reminder","Zz6Cxn":"Danger zone","pvnfJD":"Dark","o5ooMr":"Debt","WRwm0h":"Default currency","cnGeoo":"Delete","chkudi":"Delete 6pm account","VbtMs5":"Delete wallet account will also delete all related transactions!","pfa8F0":"Display name","rrOW2A":"Edit account","j1Jl7s":"Edit category","O3oNi5":"Email","QOINDn":"empty","ak+zF8":"Enable Push Notifications","/AHxlh":"Enable spending alerts","lYGfRP":"English","EmV+r3":"Enter the code sent to your email","xRPn3U":"Enter your email address","/o/2Tm":"Expense","aSBbnl":"Expenses","AL8ocL":"Family budget","xRJSOj":"From date","Weq9zb":"General","h52e9T":"Get 6pm Pro","EVORi1":"Get started by setting your monthly budget.","M1w7jC":"Grant camera permissions","Uq/imr":"If you\'re not sure, start with how much you usually spend per month.","xxsw3W":"Income","Z2b5qm":"Incomes","13aTWr":"Investing","AhuqH6":"Keeping up with your spending and budgets.","vXIe7J":"Language","brkKQW":"Left per day","PRzhQh":"Left this month","1njn7W":"Light","UC3YIm":"Login using FaceID","lkAlEG":"Magic inbox","+8Nek/":"Monthly","iBONBd":"Monthly budget","6YtxFj":"Name","xYG/fs":"Negative","XejmNR":"Negative if your content balance is under zero","6WSYbN":["New ",["0"]],"Kcr9Fr":"New account","5OdwzH":"New budget","tl5vsv":"New category","ApQ2nt":"No budget selected","xc4rPs":"No transactions","8bNIKG":"No transactions found","NuKR0h":"Others","198luN":"per day","NtQvjo":"Period","66fYpz":"Period end date","QTWhG5":"Period start date","FHx6kz":"Positive","ScJ9fj":"Privacy policy","LcET2C":"Privacy Policy","Z8pOEI":"Processing transaction...","vERlcd":"Profile","kUlL8W":"Profile updated successfully","++8ZXz":"Proudly open source","SZJG6+":"Push notifications","r7QRqI":"Push notifications are disabled","LI1qx1":"Push notifications are enabled","3yhyIW":"Push notifications are not enabled","kCxe8K":"Quarterly","j75BA9":"Rate 6pm on App Store","GkHlI/":"Revenue this month","8lh/OF":"Revenue this week","tfDRzk":"Save","y3aU20":"Save changes","uF9ruK":"Saving","WDgJiV":"Scanner","P9vd26":"Search currency...","UA6v4Z":"Seed transactions","+O3PfQ":"Select account","HfaFKV":"Select balance state","PtoMco":"Select budget type","5dfUzo":"Select period type","RoafuO":"Send feedback","wCqgpu":"Set Budget","oyi6Xa":"Set Monthly Budget","dY304N":"Set your monthly spending goal","Tz0i8g":"Settings","RDprz0":"Share with friends","5lWFkC":"Sign in","+EnZBU":"Sign in with Apple","dbWo0h":"Sign in with Google","fcWrnU":"Sign out","e+RpCP":"Sign up","TOm5Xo":"Specific dates","Q14cFX":"Spending","FlGoyI":"Spent this month","Ozoj7N":"Spent this week","w5QjWi":"Swift up to scan transaction","J8R0ve":"Swipe up to scan transaction","D+NlUC":"System","IL5Ibf":"Take a picture of your transaction","Yrrg+y":"Target","KWUgwY":"Terms & Conditions","Emv+V7":"Terms of use","OR1t9P":"This will delete the transaction. Are you sure you want to continue?","sH0pkc":"Time to enter your expenses!","w4eKlT":"To date","ecUA8p":"Today","BRMXj0":"Tomorrow","38Gho6":"Transaction created","6D8usS":"transaction note","+zy2Nq":"Type","b2vAoQ":"Uncategorized","Ef7StM":"Unknown","29VNqC":"Unknown error","VAOn4r":"Unlock","QQX2/q":"Unlocks full AI power and more!","wPTug2":"Upload new photo","KALubG":"ver.","AdWhjZ":"Verification code","fROFIL":"Vietnamese","q19YJ1":"Wallet account name","rUcnTU":"Wallet accounts","mdad9N":"Wallet Accounts","4XSc4l":"Weekly","I+fC9+":"Welcome to 6pm!","zkWmBh":"Yearly","y/0uwd":"Yesterday","kDrMSv":"Your display name"}', + '{"J/hVSQ":[["0"]],"6MIiOI":[["0"]," left"],"FEZKSz":[["language"]],"4E30de":[["remainingDays"]," days left"],"GDr6hQ":"* you can always change this later.","VE5ikN":"<0><1>Manage your expense seamlessly<2>Let <3>6pm a good time to spend","ejSd6i":"<0>By continuing, you acknowledge that you understand and agree to our <1><2>Privacy Policy","AYTmQ1":"<0>By continuing, you acknowledge that you understand and agree to the <1><2>Terms & Conditions and <3><4>Privacy Policy","LjsgKU":"0.00","y+OdTP":"Account deleted successfully","103Xyi":"Add your first transaction here","sxkWRg":"Advanced","Mxjwaz":"All accounts","pXc4dB":"All Accounts","HoJ+ka":"All entries","LcouyV":"All your data will be deleted","Vw8l6h":"An error occurred","bhrKSa":"An error occurred while deleting the transaction","rBd1BM":"An error occurred while updating the transaction","+FI+0t":"App is locked. Please authenticate to continue.","2Yw5Eq":"App settings","rg8lHb":"App theme","aAIQg2":"Appearance","rH4FJH":"Are you sure you want to delete this budget? This action cannot be undone.","TE1tui":"Are you sure you want to delete your account? This action cannot be undone.","apLLSU":"Are you sure you want to sign out?","6foA8n":"Are you sure?","X2pgJW":"Ask AI anything...","kfcRb0":"Avatar","fsBGk0":"Balance","IGsZpB":"Budgets","HjGOT5":"By day","kYFORZ":"By month","OTL6lf":"By week","HjYcC9":"Camera permissions are not granted","dEgA5A":"Cancel","dZYaqU":"Cannot extract transaction data","NUrY9o":"Categories","i+de8A":"Category name","h4wXn9":"Choose a preferred theme for the 6pm","AUYALh":"Coming soon","xGVfLh":"Continue","RvVi9c":"Continue with Email","eGKI3t":"Copied version to clipboard","PxMcud":"Current balance","AJToWu":"Current state","7cFjHo":"Daily reminder","Zz6Cxn":"Danger zone","pvnfJD":"Dark","o5ooMr":"Debt","ovBPCi":"Default","WRwm0h":"Default currency","cnGeoo":"Delete","chkudi":"Delete 6pm account","VbtMs5":"Delete wallet account will also delete all related transactions!","pfa8F0":"Display name","rrOW2A":"Edit account","j1Jl7s":"Edit category","O3oNi5":"Email","QOINDn":"empty","ak+zF8":"Enable Push Notifications","/AHxlh":"Enable spending alerts","lYGfRP":"English","EmV+r3":"Enter the code sent to your email","xRPn3U":"Enter your email address","/o/2Tm":"Expense","aSBbnl":"Expenses","AL8ocL":"Family budget","xRJSOj":"From date","Weq9zb":"General","h52e9T":"Get 6pm Pro","EVORi1":"Get started by setting your monthly budget.","M1w7jC":"Grant camera permissions","Uq/imr":"If you\'re not sure, start with how much you usually spend per month.","xxsw3W":"Income","Z2b5qm":"Incomes","13aTWr":"Investing","AhuqH6":"Keeping up with your spending and budgets.","vXIe7J":"Language","brkKQW":"Left per day","PRzhQh":"Left this month","1njn7W":"Light","UC3YIm":"Login using FaceID","lkAlEG":"Magic inbox","+8Nek/":"Monthly","iBONBd":"Monthly budget","6YtxFj":"Name","xYG/fs":"Negative","XejmNR":"Negative if your content balance is under zero","6WSYbN":["New ",["0"]],"Kcr9Fr":"New account","5OdwzH":"New budget","tl5vsv":"New category","ApQ2nt":"No budget selected","xc4rPs":"No transactions","8bNIKG":"No transactions found","NuKR0h":"Others","198luN":"per day","NtQvjo":"Period","66fYpz":"Period end date","QTWhG5":"Period start date","FHx6kz":"Positive","ScJ9fj":"Privacy policy","LcET2C":"Privacy Policy","Z8pOEI":"Processing transaction...","vERlcd":"Profile","kUlL8W":"Profile updated successfully","++8ZXz":"Proudly open source","SZJG6+":"Push notifications","r7QRqI":"Push notifications are disabled","LI1qx1":"Push notifications are enabled","3yhyIW":"Push notifications are not enabled","kCxe8K":"Quarterly","j75BA9":"Rate 6pm on App Store","GkHlI/":"Revenue this month","8lh/OF":"Revenue this week","tfDRzk":"Save","y3aU20":"Save changes","uF9ruK":"Saving","WDgJiV":"Scanner","P9vd26":"Search currency...","UA6v4Z":"Seed transactions","+O3PfQ":"Select account","HfaFKV":"Select balance state","PtoMco":"Select budget type","5dfUzo":"Select period type","RoafuO":"Send feedback","PPcets":"Set as default","wCqgpu":"Set Budget","oyi6Xa":"Set Monthly Budget","dY304N":"Set your monthly spending goal","Tz0i8g":"Settings","RDprz0":"Share with friends","5lWFkC":"Sign in","+EnZBU":"Sign in with Apple","dbWo0h":"Sign in with Google","fcWrnU":"Sign out","e+RpCP":"Sign up","TOm5Xo":"Specific dates","Q14cFX":"Spending","FlGoyI":"Spent this month","Ozoj7N":"Spent this week","w5QjWi":"Swift up to scan transaction","J8R0ve":"Swipe up to scan transaction","D+NlUC":"System","IL5Ibf":"Take a picture of your transaction","Yrrg+y":"Target","KWUgwY":"Terms & Conditions","Emv+V7":"Terms of use","OR1t9P":"This will delete the transaction. Are you sure you want to continue?","sH0pkc":"Time to enter your expenses!","w4eKlT":"To date","ecUA8p":"Today","BRMXj0":"Tomorrow","38Gho6":"Transaction created","6D8usS":"transaction note","+zy2Nq":"Type","b2vAoQ":"Uncategorized","Ef7StM":"Unknown","29VNqC":"Unknown error","VAOn4r":"Unlock","QQX2/q":"Unlocks full AI power and more!","wPTug2":"Upload new photo","KALubG":"ver.","AdWhjZ":"Verification code","fROFIL":"Vietnamese","q19YJ1":"Wallet account name","rUcnTU":"Wallet accounts","mdad9N":"Wallet Accounts","4XSc4l":"Weekly","I+fC9+":"Welcome to 6pm!","zkWmBh":"Yearly","y/0uwd":"Yesterday","kDrMSv":"Your display name"}', ) as Messages diff --git a/apps/mobile/locales/vi/messages.po b/apps/mobile/locales/vi/messages.po index 0614b899..85d22505 100644 --- a/apps/mobile/locales/vi/messages.po +++ b/apps/mobile/locales/vi/messages.po @@ -25,11 +25,11 @@ msgstr "" msgid "{language}" msgstr "" -#: apps/mobile/components/budget/budget-item.tsx:90 +#: apps/mobile/components/budget/budget-item.tsx:99 msgid "{remainingDays} days left" msgstr "còn {remainingDays} ngày" -#: apps/mobile/app/onboarding/step-two.tsx:127 +#: apps/mobile/app/onboarding/step-two.tsx:124 msgid "* you can always change this later." msgstr "* bạn có thể cập nhật lại sau." @@ -45,7 +45,7 @@ msgstr "<0>Bằng cách tiếp tục, bạn đã hiểu và đồng ý với <1> #~ msgid "<0>By continuing, you acknowledge that you understand and agree to the <1><2>Terms & Conditions and <3><4>Privacy Policy" #~ msgstr "<0>Bằng cách tiếp tục, bạn đã hiểu và đồng ý với <1><2>Điều khoản sử dụng và <3><4>Chính sách bảo mật của 6pm." -#: apps/mobile/components/budget/budget-form.tsx:120 +#: apps/mobile/components/budget/budget-form.tsx:121 #: apps/mobile/components/wallet/account-form.tsx:86 msgid "0.00" msgstr "" @@ -104,12 +104,12 @@ msgstr "Cài đặt ứng dụng" msgid "App theme" msgstr "Chủ đề ứng dụng" -#: apps/mobile/app/(app)/_layout.tsx:94 +#: apps/mobile/app/(app)/_layout.tsx:96 #: apps/mobile/app/(app)/(tabs)/settings.tsx:131 msgid "Appearance" msgstr "Giao diện" -#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:37 +#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:39 msgid "Are you sure you want to delete this budget? This action cannot be undone." msgstr "Bạn có chắc chắn muốn xóa ngân sách này? Hành động này không thể hoàn tác." @@ -158,7 +158,7 @@ msgid "Camera permissions are not granted" msgstr "Quyền truy cập camera không được cấp" #: apps/mobile/app/(app)/(tabs)/settings.tsx:248 -#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:43 +#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:45 #: apps/mobile/app/(app)/profile.tsx:120 #: apps/mobile/app/(app)/transaction/[transactionId].tsx:77 #: apps/mobile/app/(app)/wallet/[walletId].tsx:77 @@ -169,7 +169,7 @@ msgstr "Huỷ" msgid "Cannot extract transaction data" msgstr "Không thể xử lý dữ liệu giao dịch" -#: apps/mobile/app/(app)/_layout.tsx:126 +#: apps/mobile/app/(app)/_layout.tsx:128 #: apps/mobile/app/(app)/(tabs)/settings.tsx:104 msgid "Categories" msgstr "Danh mục" @@ -223,11 +223,15 @@ msgstr "Tối" msgid "Debt" msgstr "Nợ" +#: apps/mobile/components/budget/budget-item.tsx:69 +msgid "Default" +msgstr "Mặc định" + #: apps/mobile/components/setting/select-default-currency.tsx:23 msgid "Default currency" msgstr "Đơn vị mặc định" -#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:47 +#: apps/mobile/app/(app)/budget/[budgetId]/edit.tsx:49 #: apps/mobile/app/(app)/profile.tsx:124 #: apps/mobile/app/(app)/transaction/[transactionId].tsx:81 #: apps/mobile/app/(app)/wallet/[walletId].tsx:81 @@ -246,11 +250,11 @@ msgstr "Xóa tài khoản ví sẽ cũng xóa tất cả các giao dịch liên msgid "Display name" msgstr "Tên hiển thị" -#: apps/mobile/app/(app)/_layout.tsx:120 +#: apps/mobile/app/(app)/_layout.tsx:122 msgid "Edit account" msgstr "Chỉnh sửa tài khoản" -#: apps/mobile/app/(app)/_layout.tsx:147 +#: apps/mobile/app/(app)/_layout.tsx:149 msgid "Edit category" msgstr "Chỉnh sửa danh mục" @@ -291,7 +295,7 @@ msgstr "Chi tiêu" msgid "Expenses" msgstr "Chi tiêu" -#: apps/mobile/components/budget/budget-form.tsx:111 +#: apps/mobile/components/budget/budget-form.tsx:112 msgid "Family budget" msgstr "Ngân sách gia đình" @@ -315,7 +319,7 @@ msgstr "Bắt đầu bằng cách đặt ngân sách hàng tháng của bạn." msgid "Grant camera permissions" msgstr "Cấp quyền truy cập camera" -#: apps/mobile/app/onboarding/step-two.tsx:119 +#: apps/mobile/app/onboarding/step-two.tsx:116 msgid "If you're not sure, start with how much you usually spend per month." msgstr "Nếu không chắc chắn, hãy nhập số tiền bạn thường chi tiêu hàng tháng." @@ -336,7 +340,7 @@ msgstr "Đầu tư" msgid "Keeping up with your spending and budgets." msgstr "Theo dõi kịp tình hình chi tiêu và ngân sách." -#: apps/mobile/app/(app)/_layout.tsx:82 +#: apps/mobile/app/(app)/_layout.tsx:84 #: apps/mobile/app/(app)/(tabs)/settings.tsx:140 msgid "Language" msgstr "Ngôn ngữ" @@ -369,7 +373,7 @@ msgstr "Hàng tháng" msgid "Monthly budget" msgstr "Ngân sách tháng" -#: apps/mobile/components/budget/budget-form.tsx:110 +#: apps/mobile/components/budget/budget-form.tsx:111 #: apps/mobile/components/category/category-form.tsx:66 #: apps/mobile/components/wallet/account-form.tsx:69 msgid "Name" @@ -387,17 +391,17 @@ msgstr "Âm nếu số dư tài khoản dưới 0" msgid "New {0}" msgstr "Tạo mới {0}" -#: apps/mobile/app/(app)/_layout.tsx:113 +#: apps/mobile/app/(app)/_layout.tsx:115 #: apps/mobile/app/(app)/wallet/accounts.tsx:26 msgid "New account" msgstr "Tạo tài khoản mới" -#: apps/mobile/app/(app)/_layout.tsx:154 +#: apps/mobile/app/(app)/_layout.tsx:156 #: apps/mobile/app/(app)/(tabs)/_layout.tsx:80 msgid "New budget" msgstr "Tạo ngân sách" -#: apps/mobile/app/(app)/_layout.tsx:140 +#: apps/mobile/app/(app)/_layout.tsx:142 msgid "New category" msgstr "Tạo danh mục mới" @@ -417,7 +421,7 @@ msgstr "Không có giao dịch" msgid "Others" msgstr "Khác" -#: apps/mobile/components/budget/budget-item.tsx:103 +#: apps/mobile/components/budget/budget-item.tsx:112 msgid "per day" msgstr "mỗi ngày" @@ -449,7 +453,7 @@ msgstr "Chính sách bảo mật" msgid "Processing transaction..." msgstr "Đang xử lý giao dịch..." -#: apps/mobile/app/(app)/_layout.tsx:89 +#: apps/mobile/app/(app)/_layout.tsx:91 msgid "Profile" msgstr "Hồ sơ" @@ -493,7 +497,7 @@ msgstr "Doanh thu tháng này" msgid "Revenue this week" msgstr "Doanh thu tuần này" -#: apps/mobile/components/budget/budget-form.tsx:50 +#: apps/mobile/components/budget/budget-form.tsx:51 #: apps/mobile/components/category/category-form.tsx:118 #: apps/mobile/components/common/date-picker.tsx:49 #: apps/mobile/components/common/date-range-picker.tsx:56 @@ -543,6 +547,10 @@ msgstr "Chọn loại chu kỳ" msgid "Send feedback" msgstr "Gửi phản hồi" +#: apps/mobile/components/budget/budget-form.tsx:161 +msgid "Set as default" +msgstr "Đặt làm mặc định" + #: apps/mobile/app/onboarding/step-two.tsx:50 msgid "Set Budget" msgstr "Lưu Ngân Sách" @@ -551,7 +559,7 @@ msgstr "Lưu Ngân Sách" msgid "Set Monthly Budget" msgstr "Đặt Ngân Sách Tháng" -#: apps/mobile/app/onboarding/step-two.tsx:116 +#: apps/mobile/app/onboarding/step-two.tsx:113 msgid "Set your monthly spending goal" msgstr "Đặt mục tiêu chi tiêu hàng tháng" @@ -617,7 +625,7 @@ msgstr "Vuốt lên để quét giao dịch" msgid "Take a picture of your transaction" msgstr "Chụp ảnh giao dịch của bạn" -#: apps/mobile/components/budget/budget-form.tsx:119 +#: apps/mobile/components/budget/budget-form.tsx:120 msgid "Target" msgstr "Mục tiêu" @@ -649,7 +657,7 @@ msgstr "Hôm nay" msgid "Tomorrow" msgstr "Ngày mai" -#: apps/mobile/app/(app)/transaction/new-record.tsx:58 +#: apps/mobile/app/(app)/transaction/new-record.tsx:61 msgid "Transaction created" msgstr "Giao dịch đã được tạo" @@ -705,7 +713,7 @@ msgstr "Tiếng Việt" msgid "Wallet account name" msgstr "Tên tài khoản ví" -#: apps/mobile/app/(app)/_layout.tsx:99 +#: apps/mobile/app/(app)/_layout.tsx:101 #: apps/mobile/app/(app)/(tabs)/settings.tsx:95 msgid "Wallet accounts" msgstr "Quản lý tài khoản ví" diff --git a/apps/mobile/locales/vi/messages.ts b/apps/mobile/locales/vi/messages.ts index f7424185..d4be0e78 100644 --- a/apps/mobile/locales/vi/messages.ts +++ b/apps/mobile/locales/vi/messages.ts @@ -1,4 +1,4 @@ /*eslint-disable*/ import type { Messages } from '@lingui/core' export const messages = JSON.parse( - '{"J/hVSQ":[["0"]],"6MIiOI":[["0"]," còn lại"],"FEZKSz":[["language"]],"4E30de":["còn ",["remainingDays"]," ngày"],"GDr6hQ":"* bạn có thể cập nhật lại sau.","VE5ikN":"<0><1>Quản lý chi tiêu hiệu quả<2>Không lo cháy túi mỗi <3>6pm","ejSd6i":"<0>Bằng cách tiếp tục, bạn đã hiểu và đồng ý với <1><2>Chính sách bảo mật của 6pm.","AYTmQ1":"<0>Bằng cách tiếp tục, bạn đã hiểu và đồng ý với <1><2>Điều khoản sử dụng và <3><4>Chính sách bảo mật của 6pm.","LjsgKU":"0.00","y+OdTP":"Xóa tài khoản thành công","103Xyi":"Thêm giao dịch đầu tiên ở đây","sxkWRg":"Nâng cao","Mxjwaz":"Tất cả tài khoản","pXc4dB":"Tất cả tài khoản","HoJ+ka":"Xem tất cả","LcouyV":"Tất cả dữ liệu của bạn sẽ bị xóa","Vw8l6h":"Có lỗi xảy ra","bhrKSa":"Có lỗi xảy ra khi xóa giao dịch","rBd1BM":"Có lỗi xảy ra khi cập nhật giao dịch","+FI+0t":"Ứng dụng đã khóa. Vui lòng xác thực để tiếp tục.","2Yw5Eq":"Cài đặt ứng dụng","rg8lHb":"Chủ đề ứng dụng","aAIQg2":"Giao diện","rH4FJH":"Bạn có chắc chắn muốn xóa ngân sách này? Hành động này không thể hoàn tác.","TE1tui":"Bạn có chắc chắn muốn xóa tài khoản của bạn? Hành động này không thể hoàn tác.","apLLSU":"Bạn có chắc chắn muốn đăng xuất?","6foA8n":"Bạn chắc chưa?","X2pgJW":"Hỏi AI bất kỳ gì...","kfcRb0":"Ảnh đại diện","fsBGk0":"Số dư","IGsZpB":"Ngân sách","HjGOT5":"Theo ngày","kYFORZ":"Theo tháng","OTL6lf":"Theo tuần","HjYcC9":"Quyền truy cập camera không được cấp","dEgA5A":"Huỷ","dZYaqU":"Không thể xử lý dữ liệu giao dịch","NUrY9o":"Danh mục","i+de8A":"Tên danh mục","h4wXn9":"Chọn chủ đề giao diện cho 6pm","AUYALh":"Sắp xong","xGVfLh":"Tiếp tục","RvVi9c":"Tiếp tục với Email","eGKI3t":"Đã sao chép số phiên bản","PxMcud":"Số dư hiện tại","AJToWu":"Trạng thái","7cFjHo":"Nhắc nhở hàng ngày","Zz6Cxn":"Vùng nguy hiểm","pvnfJD":"Tối","o5ooMr":"Nợ","WRwm0h":"Đơn vị mặc định","cnGeoo":"Xóa","chkudi":"Xóa tài khoản 6pm","VbtMs5":"Xóa tài khoản ví sẽ cũng xóa tất cả các giao dịch liên quan!","pfa8F0":"Tên hiển thị","rrOW2A":"Chỉnh sửa tài khoản","j1Jl7s":"Chỉnh sửa danh mục","O3oNi5":"Email","QOINDn":"trống","ak+zF8":"Bật Thông Báo Đẩy","/AHxlh":"Nhận thông báo chi tiêu","lYGfRP":"Tiếng Anh","EmV+r3":"Nhập mã xác nhận gửi đến email của bạn","xRPn3U":"Nhập địa chỉ email của bạn","/o/2Tm":"Chi tiêu","aSBbnl":"Chi tiêu","AL8ocL":"Ngân sách gia đình","xRJSOj":"Từ ngày","Weq9zb":"Chung","h52e9T":"Nâng Cấp 6pm Pro","EVORi1":"Bắt đầu bằng cách đặt ngân sách hàng tháng của bạn.","M1w7jC":"Cấp quyền truy cập camera","Uq/imr":"Nếu không chắc chắn, hãy nhập số tiền bạn thường chi tiêu hàng tháng.","xxsw3W":"Thu nhập","Z2b5qm":"Thu nhập","13aTWr":"Đầu tư","AhuqH6":"Theo dõi kịp tình hình chi tiêu và ngân sách.","vXIe7J":"Ngôn ngữ","brkKQW":"Còn lại mỗi ngày","PRzhQh":"Còn lại tháng này","1njn7W":"Sáng","UC3YIm":"Đăng nhập bằng FaceID","lkAlEG":"Hộp thư ma thuật","+8Nek/":"Hàng tháng","iBONBd":"Ngân sách tháng","6YtxFj":"Tên","xYG/fs":"Âm","XejmNR":"Âm nếu số dư tài khoản dưới 0","6WSYbN":["Tạo mới ",["0"]],"Kcr9Fr":"Tạo tài khoản mới","5OdwzH":"Tạo ngân sách","tl5vsv":"Tạo danh mục mới","ApQ2nt":"Chọn ngân sách","xc4rPs":"Không có giao dịch","8bNIKG":"Không tìm thấy giao dịch","NuKR0h":"Khác","198luN":"mỗi ngày","NtQvjo":"Period","66fYpz":"Ngày kết thúc","QTWhG5":"Ngày bắt đầu","FHx6kz":"Dương","ScJ9fj":"Chính sách bảo mật","LcET2C":"Chính sách bảo mật","Z8pOEI":"Đang xử lý giao dịch...","vERlcd":"Hồ sơ","kUlL8W":"Cập nhật hồ sơ thành công","++8ZXz":"Mã nguồn mở","SZJG6+":"Thông báo đẩy","r7QRqI":"Thông báo đẩy bị vô hiệu hóa","LI1qx1":"Thông báo đẩy đã được bật","3yhyIW":"Thông báo đẩy chưa được bật","kCxe8K":"Hàng quý","j75BA9":"Đánh giá 6pm trên App Store","GkHlI/":"Doanh thu tháng này","8lh/OF":"Doanh thu tuần này","tfDRzk":"Lưu","y3aU20":"Lưu thay đổi","uF9ruK":"Đang lưu","WDgJiV":"Quét hoá đơn","P9vd26":"Tìm kiếm đơn vị...","UA6v4Z":"Tạo giao dịch mẫu","+O3PfQ":"Chọn tài khoản","HfaFKV":"Chọn trạng thái số dư","PtoMco":"Chọn loại ngân sách","5dfUzo":"Chọn loại chu kỳ","RoafuO":"Gửi phản hồi","wCqgpu":"Lưu Ngân Sách","oyi6Xa":"Đặt Ngân Sách Tháng","dY304N":"Đặt mục tiêu chi tiêu hàng tháng","Tz0i8g":"Cài đặt","RDprz0":"Chia sẻ với bạn bè","5lWFkC":"Đăng nhập","+EnZBU":"Tiếp tục với Apple","dbWo0h":"Tiếp tục với Google","fcWrnU":"Đăng xuất","e+RpCP":"Đăng ký","TOm5Xo":"Ngày cụ thể","Q14cFX":"Chi tiêu","FlGoyI":"Chi tiêu tháng này","Ozoj7N":"Chi tiêu tuần này","w5QjWi":"Vuốt lên để quét giao dịch","J8R0ve":"Vuốt lên để quét giao dịch","D+NlUC":"Hệ thống","IL5Ibf":"Chụp ảnh giao dịch của bạn","Yrrg+y":"Mục tiêu","KWUgwY":"Điều khoản sử dụng","Emv+V7":"Điều khoản sử dụng","OR1t9P":"Hành động này sẽ xóa giao dịch. Bạn có chắc chắn muốn tiếp tục không?","sH0pkc":"Đến giờ nhập chi tiêu hôm nay!","w4eKlT":"Đến ngày","ecUA8p":"Hôm nay","BRMXj0":"Ngày mai","38Gho6":"Giao dịch đã được tạo","6D8usS":"ghi chú giao dịch","+zy2Nq":"Loại","b2vAoQ":"Chưa phân loại","Ef7StM":"Không xác định","29VNqC":"Lỗi không xác định","VAOn4r":"Mở khóa","QQX2/q":"Mở khóa sức mạnh AI và các tính năng khác!","wPTug2":"Tải lên ảnh mới","KALubG":"ver.","AdWhjZ":"Mã xác nhận","fROFIL":"Tiếng Việt","q19YJ1":"Tên tài khoản ví","rUcnTU":"Quản lý tài khoản ví","mdad9N":"Các tài khoản","4XSc4l":"Hàng tuần","I+fC9+":"Chào mừng đến 6pm!","zkWmBh":"Hàng năm","y/0uwd":"Hôm qua","kDrMSv":"Tên hiển thị của bạn"}', + '{"J/hVSQ":[["0"]],"6MIiOI":[["0"]," còn lại"],"FEZKSz":[["language"]],"4E30de":["còn ",["remainingDays"]," ngày"],"GDr6hQ":"* bạn có thể cập nhật lại sau.","VE5ikN":"<0><1>Quản lý chi tiêu hiệu quả<2>Không lo cháy túi mỗi <3>6pm","ejSd6i":"<0>Bằng cách tiếp tục, bạn đã hiểu và đồng ý với <1><2>Chính sách bảo mật của 6pm.","AYTmQ1":"<0>Bằng cách tiếp tục, bạn đã hiểu và đồng ý với <1><2>Điều khoản sử dụng và <3><4>Chính sách bảo mật của 6pm.","LjsgKU":"0.00","y+OdTP":"Xóa tài khoản thành công","103Xyi":"Thêm giao dịch đầu tiên ở đây","sxkWRg":"Nâng cao","Mxjwaz":"Tất cả tài khoản","pXc4dB":"Tất cả tài khoản","HoJ+ka":"Xem tất cả","LcouyV":"Tất cả dữ liệu của bạn sẽ bị xóa","Vw8l6h":"Có lỗi xảy ra","bhrKSa":"Có lỗi xảy ra khi xóa giao dịch","rBd1BM":"Có lỗi xảy ra khi cập nhật giao dịch","+FI+0t":"Ứng dụng đã khóa. Vui lòng xác thực để tiếp tục.","2Yw5Eq":"Cài đặt ứng dụng","rg8lHb":"Chủ đề ứng dụng","aAIQg2":"Giao diện","rH4FJH":"Bạn có chắc chắn muốn xóa ngân sách này? Hành động này không thể hoàn tác.","TE1tui":"Bạn có chắc chắn muốn xóa tài khoản của bạn? Hành động này không thể hoàn tác.","apLLSU":"Bạn có chắc chắn muốn đăng xuất?","6foA8n":"Bạn chắc chưa?","X2pgJW":"Hỏi AI bất kỳ gì...","kfcRb0":"Ảnh đại diện","fsBGk0":"Số dư","IGsZpB":"Ngân sách","HjGOT5":"Theo ngày","kYFORZ":"Theo tháng","OTL6lf":"Theo tuần","HjYcC9":"Quyền truy cập camera không được cấp","dEgA5A":"Huỷ","dZYaqU":"Không thể xử lý dữ liệu giao dịch","NUrY9o":"Danh mục","i+de8A":"Tên danh mục","h4wXn9":"Chọn chủ đề giao diện cho 6pm","AUYALh":"Sắp xong","xGVfLh":"Tiếp tục","RvVi9c":"Tiếp tục với Email","eGKI3t":"Đã sao chép số phiên bản","PxMcud":"Số dư hiện tại","AJToWu":"Trạng thái","7cFjHo":"Nhắc nhở hàng ngày","Zz6Cxn":"Vùng nguy hiểm","pvnfJD":"Tối","o5ooMr":"Nợ","ovBPCi":"Mặc định","WRwm0h":"Đơn vị mặc định","cnGeoo":"Xóa","chkudi":"Xóa tài khoản 6pm","VbtMs5":"Xóa tài khoản ví sẽ cũng xóa tất cả các giao dịch liên quan!","pfa8F0":"Tên hiển thị","rrOW2A":"Chỉnh sửa tài khoản","j1Jl7s":"Chỉnh sửa danh mục","O3oNi5":"Email","QOINDn":"trống","ak+zF8":"Bật Thông Báo Đẩy","/AHxlh":"Nhận thông báo chi tiêu","lYGfRP":"Tiếng Anh","EmV+r3":"Nhập mã xác nhận gửi đến email của bạn","xRPn3U":"Nhập địa chỉ email của bạn","/o/2Tm":"Chi tiêu","aSBbnl":"Chi tiêu","AL8ocL":"Ngân sách gia đình","xRJSOj":"Từ ngày","Weq9zb":"Chung","h52e9T":"Nâng Cấp 6pm Pro","EVORi1":"Bắt đầu bằng cách đặt ngân sách hàng tháng của bạn.","M1w7jC":"Cấp quyền truy cập camera","Uq/imr":"Nếu không chắc chắn, hãy nhập số tiền bạn thường chi tiêu hàng tháng.","xxsw3W":"Thu nhập","Z2b5qm":"Thu nhập","13aTWr":"Đầu tư","AhuqH6":"Theo dõi kịp tình hình chi tiêu và ngân sách.","vXIe7J":"Ngôn ngữ","brkKQW":"Còn lại mỗi ngày","PRzhQh":"Còn lại tháng này","1njn7W":"Sáng","UC3YIm":"Đăng nhập bằng FaceID","lkAlEG":"Hộp thư ma thuật","+8Nek/":"Hàng tháng","iBONBd":"Ngân sách tháng","6YtxFj":"Tên","xYG/fs":"Âm","XejmNR":"Âm nếu số dư tài khoản dưới 0","6WSYbN":["Tạo mới ",["0"]],"Kcr9Fr":"Tạo tài khoản mới","5OdwzH":"Tạo ngân sách","tl5vsv":"Tạo danh mục mới","ApQ2nt":"Chọn ngân sách","xc4rPs":"Không có giao dịch","8bNIKG":"Không tìm thấy giao dịch","NuKR0h":"Khác","198luN":"mỗi ngày","NtQvjo":"Period","66fYpz":"Ngày kết thúc","QTWhG5":"Ngày bắt đầu","FHx6kz":"Dương","ScJ9fj":"Chính sách bảo mật","LcET2C":"Chính sách bảo mật","Z8pOEI":"Đang xử lý giao dịch...","vERlcd":"Hồ sơ","kUlL8W":"Cập nhật hồ sơ thành công","++8ZXz":"Mã nguồn mở","SZJG6+":"Thông báo đẩy","r7QRqI":"Thông báo đẩy bị vô hiệu hóa","LI1qx1":"Thông báo đẩy đã được bật","3yhyIW":"Thông báo đẩy chưa được bật","kCxe8K":"Hàng quý","j75BA9":"Đánh giá 6pm trên App Store","GkHlI/":"Doanh thu tháng này","8lh/OF":"Doanh thu tuần này","tfDRzk":"Lưu","y3aU20":"Lưu thay đổi","uF9ruK":"Đang lưu","WDgJiV":"Quét hoá đơn","P9vd26":"Tìm kiếm đơn vị...","UA6v4Z":"Tạo giao dịch mẫu","+O3PfQ":"Chọn tài khoản","HfaFKV":"Chọn trạng thái số dư","PtoMco":"Chọn loại ngân sách","5dfUzo":"Chọn loại chu kỳ","RoafuO":"Gửi phản hồi","PPcets":"Đặt làm mặc định","wCqgpu":"Lưu Ngân Sách","oyi6Xa":"Đặt Ngân Sách Tháng","dY304N":"Đặt mục tiêu chi tiêu hàng tháng","Tz0i8g":"Cài đặt","RDprz0":"Chia sẻ với bạn bè","5lWFkC":"Đăng nhập","+EnZBU":"Tiếp tục với Apple","dbWo0h":"Tiếp tục với Google","fcWrnU":"Đăng xuất","e+RpCP":"Đăng ký","TOm5Xo":"Ngày cụ thể","Q14cFX":"Chi tiêu","FlGoyI":"Chi tiêu tháng này","Ozoj7N":"Chi tiêu tuần này","w5QjWi":"Vuốt lên để quét giao dịch","J8R0ve":"Vuốt lên để quét giao dịch","D+NlUC":"Hệ thống","IL5Ibf":"Chụp ảnh giao dịch của bạn","Yrrg+y":"Mục tiêu","KWUgwY":"Điều khoản sử dụng","Emv+V7":"Điều khoản sử dụng","OR1t9P":"Hành động này sẽ xóa giao dịch. Bạn có chắc chắn muốn tiếp tục không?","sH0pkc":"Đến giờ nhập chi tiêu hôm nay!","w4eKlT":"Đến ngày","ecUA8p":"Hôm nay","BRMXj0":"Ngày mai","38Gho6":"Giao dịch đã được tạo","6D8usS":"ghi chú giao dịch","+zy2Nq":"Loại","b2vAoQ":"Chưa phân loại","Ef7StM":"Không xác định","29VNqC":"Lỗi không xác định","VAOn4r":"Mở khóa","QQX2/q":"Mở khóa sức mạnh AI và các tính năng khác!","wPTug2":"Tải lên ảnh mới","KALubG":"ver.","AdWhjZ":"Mã xác nhận","fROFIL":"Tiếng Việt","q19YJ1":"Tên tài khoản ví","rUcnTU":"Quản lý tài khoản ví","mdad9N":"Các tài khoản","4XSc4l":"Hàng tuần","I+fC9+":"Chào mừng đến 6pm!","zkWmBh":"Hàng năm","y/0uwd":"Hôm qua","kDrMSv":"Tên hiển thị của bạn"}', ) as Messages diff --git a/apps/mobile/package.json b/apps/mobile/package.json index 50e36452..1b96834b 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -46,6 +46,7 @@ "@rn-primitives/progress": "^1.0.3", "@rn-primitives/select": "^1.0.3", "@rn-primitives/slot": "^1.0.3", + "@rn-primitives/switch": "^1.0.3", "@rn-primitives/types": "^1.0.3", "@sentry/react-native": "~5.26.0", "@shopify/react-native-skia": "1.2.3", diff --git a/packages/validation/src/budget.zod.ts b/packages/validation/src/budget.zod.ts index 07a3ed97..02e4f24d 100644 --- a/packages/validation/src/budget.zod.ts +++ b/packages/validation/src/budget.zod.ts @@ -26,6 +26,7 @@ export const zCreateBudget = z.object({ } return true }, 'Select period range'), + isDefault: z.boolean().optional(), }) export type CreateBudget = z.infer @@ -51,6 +52,7 @@ export const zUpdateBudget = z.object({ } return true }, 'Select period range'), + isDefault: z.boolean().optional(), }) export type UpdateBudget = z.infer diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d57d6898..a5746228 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -189,6 +189,9 @@ importers: '@rn-primitives/slot': specifier: ^1.0.3 version: 1.0.3(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1) + '@rn-primitives/switch': + specifier: ^1.0.3 + version: 1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1) '@rn-primitives/types': specifier: ^1.0.3 version: 1.0.3(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1) @@ -2642,6 +2645,18 @@ packages: react-native-web: optional: true + '@rn-primitives/switch@1.0.3': + resolution: {integrity: sha512-bzgRcdBw8myXeHerGxZw1bhhP7afqkj0N0nzcWmK0o9Epr70b++X1LkIFe0//BGsTkrulb02aJEkVg6UOgez3g==} + peerDependencies: + react: '*' + react-native: '*' + react-native-web: '*' + peerDependenciesMeta: + react-native: + optional: true + react-native-web: + optional: true + '@rn-primitives/types@1.0.3': resolution: {integrity: sha512-5GY4J6SBN2JosYS/8bvQZOZL+HZk85COaFlNnjiL3efoa9gH+v1dNi0F2gW/Gr0PuGF/xo/z0iOiVc5KrDsAkQ==} peerDependencies: @@ -10539,6 +10554,20 @@ snapshots: react-native: 0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1) react-native-web: 0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rn-primitives/switch@1.0.3(@types/react-dom@18.3.0)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-switch': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@rn-primitives/slot': 1.0.3(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1) + '@rn-primitives/types': 1.0.3(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1) + react: 18.3.1 + optionalDependencies: + react-native: 0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1) + react-native-web: 0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + - react-dom + '@rn-primitives/types@1.0.3(react-native-web@0.19.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-native@0.74.2(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(@types/react@18.2.79)(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1