178 lines
5.1 KiB
HTML
178 lines
5.1 KiB
HTML
import type { FinanceRecord } from '@/types/finance/record'
|
|
import Big from 'big.js'
|
|
import { useEffect, useState } from 'react'
|
|
import { Keyboard, Pressable, StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native'
|
|
import { ADatePicker, AInput, LucideIcon } from '@/components/common/ao/index'
|
|
import { useKeyboardHeight } from '@/hooks/useKeyboardHeight'
|
|
import { getCurrentDate } from '@/utils/time'
|
|
|
|
interface KeydownItem {
|
|
key: string | number
|
|
content: React.ReactNode
|
|
}
|
|
|
|
interface AmountKeyboardProps {
|
|
show?: boolean
|
|
record: FinanceRecord
|
|
|
|
// 可选:点击完成按钮触发
|
|
onDone?: (record: FinanceRecord) => void
|
|
}
|
|
|
|
export default function AmountKeyboard({
|
|
show = false,
|
|
record,
|
|
onDone,
|
|
}: AmountKeyboardProps) {
|
|
// 自定义键盘计算过程
|
|
const [keydownInput, setKeydownInput] = useState('')
|
|
// 日期选择
|
|
const [showDatePicker, setShowDatePicker] = useState(false)
|
|
// 备注聚焦
|
|
const [remarkIsFocused, setRemarkIsFocused] = useState(false)
|
|
// 键盘高度
|
|
const keyboardHeight = useKeyboardHeight()
|
|
|
|
const [innerRecord, setInnerRecord] = useState<FinanceRecord>({
|
|
id: 0,
|
|
category_id: 0,
|
|
amount: '',
|
|
remark: '',
|
|
record_time: '',
|
|
member_id: 0,
|
|
member_name: '',
|
|
})
|
|
|
|
useEffect(() => {
|
|
setInnerRecord(record)
|
|
setKeydownInput(record.amount || '0.00')
|
|
}, [record])
|
|
|
|
useEffect(() => {
|
|
if (!keydownInput) {
|
|
setInnerRecord({
|
|
...innerRecord,
|
|
amount: '0',
|
|
})
|
|
return
|
|
}
|
|
|
|
try {
|
|
setInnerRecord({
|
|
...innerRecord,
|
|
amount: calculateWithBig(keydownInput),
|
|
})
|
|
}
|
|
catch {
|
|
setInnerRecord({
|
|
...innerRecord,
|
|
amount: '0',
|
|
})
|
|
}
|
|
}, [keydownInput])
|
|
|
|
return (
|
|
<View style={{
|
|
backgroundColor: '#fff',
|
|
elevation: 20,
|
|
}}
|
|
>
|
|
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
|
|
<View className="h-28 flex pl-4 pr-4 justify-center">
|
|
<View className="flex flex-row items-center justify-between">
|
|
<Pressable
|
|
className="flex flex-row items-center gap-1.5 px-2 py-1.5 rounded-md bg-gray-50 active:opacity-70"
|
|
onPress={() => setShowDatePicker(true)}
|
|
>
|
|
<LucideIcon icon="Calendar" size={16} color="#60a5fa" clickable={false} />
|
|
<Text className="text-gray-600 text-sm">{innerRecord.record_time}</Text>
|
|
<LucideIcon icon="ChevronDown" size={12} color="#aaa" clickable={false} />
|
|
</Pressable>
|
|
<Text className="text-3xl text-blue-700 text-right">{innerRecord.amount}</Text>
|
|
</View>
|
|
|
|
<Text className="text-gray-400 text-right">{keydownInput}</Text>
|
|
<AInput
|
|
value={innerRecord.remark}
|
|
placeholder="备注"
|
|
className="bg-[#f2f3f5] border-0"
|
|
size="sm"
|
|
onChangeText={(val) => {
|
|
setInnerRecord({
|
|
...innerRecord,
|
|
remark: val,
|
|
})
|
|
}}
|
|
onFocus={() => setRemarkIsFocused(true)}
|
|
onBlur={() => setRemarkIsFocused(false)}
|
|
/>
|
|
</View>
|
|
</TouchableWithoutFeedback>
|
|
<View className="flex flex-row flex-wrap" style={{ height: 220 }}>
|
|
{keys.map((item, idx) => {
|
|
const isFirstCol = idx % 4 === 0
|
|
const isFirstRow = idx < 4
|
|
const isLastCol = (idx + 1) % 4 === 0
|
|
const isLastRow = idx >= 12
|
|
|
|
return (
|
|
<Pressable
|
|
key={item.key}
|
|
onPress={() => handlePress(item.key)}
|
|
style={{
|
|
width: '25%',
|
|
height: '25%',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
borderTopWidth: isFirstRow ? 0.3 : 0,
|
|
borderLeftWidth: isFirstCol ? 0.3 : 0,
|
|
borderRightWidth: !isLastCol ? 0.3 : 0,
|
|
borderBottomWidth: !isLastRow ? 0.3 : 0,
|
|
borderColor: '#ddd',
|
|
}}
|
|
>
|
|
{({ pressed }) => {
|
|
const defaultBg = item.key === '/' ? '#e6d7b8' : '#fff'
|
|
const pressedBg = item.key === '/' ? '#f5e9d4' : '#f2f2f2'
|
|
|
|
return (
|
|
<>
|
|
<View
|
|
style={{
|
|
...StyleSheet.absoluteFillObject,
|
|
backgroundColor: pressed ? pressedBg : defaultBg,
|
|
}}
|
|
/>
|
|
{item.content}
|
|
</>
|
|
)
|
|
}}
|
|
</Pressable>
|
|
)
|
|
})}
|
|
</View>
|
|
{remarkIsFocused && keyboardHeight > 220 && (
|
|
<View style={{ height: keyboardHeight + 10 - 220 }} />
|
|
)}
|
|
|
|
<ADatePicker
|
|
pickerTitle="记账时间"
|
|
mode="date"
|
|
date={innerRecord.record_time}
|
|
show={showDatePicker}
|
|
onClose={() => {
|
|
setShowDatePicker(false)
|
|
}}
|
|
onConfirm={(date) => {
|
|
setShowDatePicker(false)
|
|
|
|
setInnerRecord({
|
|
...innerRecord,
|
|
record_time: date,
|
|
})
|
|
}}
|
|
/>
|
|
</View>
|
|
)
|
|
}
|