This commit is contained in:
oneao committed 2026-01-14 22:25:14 +08:00
1 parent cb4562361a
commit b38583a9fe
11 files changed
+174 -85

No files matched your search

@@ -1,37 +1,67 @@
import { useEffect, useState } from 'react'
import { Pressable, ScrollView, Text, View } from 'react-native'
import { Pressable, Text, View } from 'react-native'
import { AButton } from '@/components/common/ao'
import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
import {
Drawer,
DrawerBackdrop,
DrawerBody,
DrawerContent,
DrawerFooter,
DrawerHeader,
} from '@/components/ui/drawer'
import { Input, InputField } from '@/components/ui/input'
import { useMoneyCategoryStore } from '@/store/moneyCategory'
import { MoneyCategoryEnum } from '@/types/money/category'
interface CreateCategoryProps {
open: boolean
onClose?: () => void
type: MoneyCategoryEnum
}
interface CreateCategoryForm {
icon: string
name: string
}
export default function CreateCategory({
open,
onClose,
type,
}: CreateCategoryProps) {
const moneyCategoryStore = useMoneyCategoryStore()
const [isOpen, setIsOpen] = useState(open)
const [form, setForm] = useState<CreateCategoryForm>({
icon: '',
name: '',
})
const [confirmDisabled, setConfirmDisabled] = useState(true)
const [confirmLoading, setConfirmLoading] = useState(false)
useEffect(() => {
setIsOpen(open)
}, [open])
useEffect(() => {
if (form.name && form.name.length < 6) {
setConfirmDisabled(false)
}
else {
setConfirmDisabled(true)
}
}, [form.name])
function handleClose() {
setIsOpen(false)
onClose && onClose()
setForm({
icon: '',
name: '',
})
}
return (
@@ -45,60 +75,65 @@ export default function CreateCategory({
>
<DrawerHeader className="px-4 flex flex-col gap-4">
<View className="flex flex-row items-center justify-between w-full">
<Pressable>
<Text className="text-gray-600">取消</Text>
</Pressable>
<AButton size="xs" variant="outline" onPress={handleClose}>取消</AButton>
<Text className="text-xl font-medium">类别</Text>
<Text className="text-lg font-medium">{type === MoneyCategoryEnum.Expense ? '添加支出分类' : '添加收入分类'}</Text>
<Pressable>
<Text className="text-gray-600">确认</Text>
</Pressable>
<AButton size="xs" disabled={confirmDisabled} loading={confirmLoading}>确认</AButton>
</View>
<Input
variant="outline"
>
<InputField placeholder="请输入名称" />
<InputField placeholder="请输入名称(不超过5个字符)" />
</Input>
</DrawerHeader>
<DrawerBody>
<ScrollView className="flex-1">
{Object.entries(moneyCategoryStore.ICON_GROUPS).map(([groupName, icons]) => (
<View key={groupName} className="mb-4">
<Text className="text-center mb-4">
{groupName}
</Text>
<DrawerBody className="mb-16">
{Object.entries(moneyCategoryStore.ICON_GROUPS).map(([groupName, icons]) => (
<View key={groupName} className="mb-2">
<Text className="text-center text-sm mb-4">
{groupName}
</Text>
<View className="flex flex-row flex-wrap">
{icons.map(icon => (
<Pressable
key={icon}
className="w-1/5 mb-3 flex items-center"
onPress={() => {
console.log('select icon:', icon)
<View className="flex flex-row flex-wrap">
{icons.map(icon => (
<Pressable
key={icon}
className="w-1/5 mb-3 flex items-center"
onPress={() => {
setForm(val => ({
...val,
icon,
}))
}}
>
<View
style={{
width: 46,
height: 46,
borderRadius: 28,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: icon === form.icon ? '#333' : '#F3F4F6',
}}
>
<View
style={{
width: 46,
height: 46,
borderRadius: 28,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F3F4F6',
}}
>
<MoneyCategoryIcon name={icon} size={28} />
</View>
</Pressable>
))}
</View>
<MoneyCategoryIcon
name={icon}
size={32}
color={
icon === form.icon ? '#fff' : '#000'
}
/>
</View>
</Pressable>
))}
</View>
))}
</ScrollView>
</View>
))}
</DrawerBody>
<DrawerFooter />
</DrawerContent>
</Drawer>
)
@@ -9,10 +9,11 @@ import { AButton, ATab, LucideIcon } from '@/components/common/ao'
import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
import CustomHeader from '@/components/custom/Header'
import { useMoneyCategoryStore } from '@/store/moneyCategory'
import { MoneyCategoryEnum } from '@/types/money/category'
import CreateCategory from './components/CreateCategory'
export default function MoneyCategorySetting() {
const [selectedTab, setSelectedTab] = useState(0)
const [selectedTab, setSelectedTab] = useState(MoneyCategoryEnum.Expense)
const moneyCategoryStore = useMoneyCategoryStore()
const scrollableRef = useAnimatedRef<Animated.ScrollView>()
@@ -25,7 +26,7 @@ export default function MoneyCategorySetting() {
const [openCreateCategory, setOpenCreateCategory] = useState<boolean>(false)
useEffect(() => {
setCategories(selectedTab === 0 ? moneyCategoryStore.getExpenseCategories() : moneyCategoryStore.getIncomeCategories())
setCategories(selectedTab === MoneyCategoryEnum.Expense ? moneyCategoryStore.getExpenseCategories() : moneyCategoryStore.getIncomeCategories())
}, [selectedTab])
const renderItem = useCallback<SortableGridRenderItem<MoneyCategoryItem>>(
@@ -69,18 +70,18 @@ export default function MoneyCategorySetting() {
<View className="flex-1">
<View className="pt-2 mb-4 px-3 flex flex-row items-center justify-between">
<ATab
defaultIndex={selectedTab}
onChange={(index) => {
setSelectedTab(index)
defaultKey={selectedTab}
onChange={(key) => {
setSelectedTab(key as MoneyCategoryEnum)
}}
data={[
{
key: 'income',
label: '收入',
key: MoneyCategoryEnum.Expense,
label: '支出',
},
{
key: 'expense',
label: '支出',
key: MoneyCategoryEnum.Income,
label: '收入',
},
]}
/>
@@ -189,6 +190,7 @@ export default function MoneyCategorySetting() {
</View>
<CreateCategory
type={selectedTab}
open={openCreateCategory}
onClose={() => setOpenCreateCategory(false)}
/>