159 lines
4.4 KiB
TypeScript
159 lines
4.4 KiB
TypeScript
"use client"
|
|
|
|
import { useState, useEffect } from "react"
|
|
|
|
export interface LocalFinanceProduct {
|
|
id: string
|
|
principal: number
|
|
depositDate: Date | null
|
|
endDate: Date | null
|
|
currentNetValue: number | null
|
|
annualRate: number | null
|
|
profit: number | null
|
|
dailyProfit: number | null
|
|
monthlyProfit: number | null
|
|
calculatedAnnualRate: number | null
|
|
averageAnnualProfit: number | null
|
|
currency: string
|
|
notes: string | null
|
|
createdAt: Date
|
|
updatedAt: Date
|
|
}
|
|
|
|
const STORAGE_KEY = 'finance-calculator-products'
|
|
|
|
export function useLocalStorage() {
|
|
const [products, setProducts] = useState<LocalFinanceProduct[]>([])
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
|
|
// 从本地存储加载数据
|
|
useEffect(() => {
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY)
|
|
if (stored) {
|
|
const parsedProducts = JSON.parse(stored).map((product: any) => ({
|
|
...product,
|
|
depositDate: product.depositDate ? new Date(product.depositDate) : null,
|
|
endDate: product.endDate ? new Date(product.endDate) : null,
|
|
createdAt: new Date(product.createdAt),
|
|
updatedAt: new Date(product.updatedAt),
|
|
}))
|
|
setProducts(parsedProducts)
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load local storage data:', error)
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
// 保存数据到本地存储
|
|
const saveToLocal = (newProducts: LocalFinanceProduct[]) => {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(newProducts))
|
|
setProducts(newProducts)
|
|
} catch (error) {
|
|
console.error('Failed to save to local storage:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// 添加产品到本地存储
|
|
const addProduct = (productData: Omit<LocalFinanceProduct, 'id' | 'createdAt' | 'updatedAt' | 'profit' | 'dailyProfit' | 'monthlyProfit' | 'calculatedAnnualRate' | 'averageAnnualProfit'>) => {
|
|
const now = new Date()
|
|
const newProduct: LocalFinanceProduct = {
|
|
...productData,
|
|
id: `local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
profit: null,
|
|
dailyProfit: null,
|
|
monthlyProfit: null,
|
|
calculatedAnnualRate: null,
|
|
averageAnnualProfit: null,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
}
|
|
|
|
// 计算收益相关数据
|
|
const calculatedProduct = calculateProductStats(newProduct)
|
|
const newProducts = [calculatedProduct, ...products]
|
|
saveToLocal(newProducts)
|
|
return calculatedProduct
|
|
}
|
|
|
|
// 更新产品
|
|
const updateProduct = (id: string, updates: Partial<LocalFinanceProduct>) => {
|
|
const updatedProducts = products.map(product => {
|
|
if (product.id === id) {
|
|
const updatedProduct = { ...product, ...updates, updatedAt: new Date() }
|
|
return calculateProductStats(updatedProduct)
|
|
}
|
|
return product
|
|
})
|
|
saveToLocal(updatedProducts)
|
|
}
|
|
|
|
// 删除产品
|
|
const removeProduct = (id: string) => {
|
|
const newProducts = products.filter(product => product.id !== id)
|
|
saveToLocal(newProducts)
|
|
}
|
|
|
|
// 清空本地存储
|
|
const clearLocal = () => {
|
|
localStorage.removeItem(STORAGE_KEY)
|
|
setProducts([])
|
|
}
|
|
|
|
// 获取所有本地数据(用于同步)
|
|
const getAllLocalData = () => {
|
|
return products
|
|
}
|
|
|
|
// 检查是否有本地数据
|
|
const hasLocalData = () => {
|
|
return products.length > 0
|
|
}
|
|
|
|
return {
|
|
products,
|
|
isLoading,
|
|
addProduct,
|
|
updateProduct,
|
|
removeProduct,
|
|
clearLocal,
|
|
getAllLocalData,
|
|
hasLocalData,
|
|
}
|
|
}
|
|
|
|
// 计算产品统计数据的辅助函数
|
|
function calculateProductStats(product: LocalFinanceProduct): LocalFinanceProduct {
|
|
let profit = null
|
|
let dailyProfit = null
|
|
let monthlyProfit = null
|
|
let calculatedAnnualRate = null
|
|
let averageAnnualProfit = null
|
|
|
|
if (product.currentNetValue && product.principal) {
|
|
profit = product.currentNetValue - product.principal
|
|
|
|
if (product.depositDate && product.endDate) {
|
|
const days = Math.ceil((product.endDate.getTime() - product.depositDate.getTime()) / (1000 * 60 * 60 * 24))
|
|
if (days > 0) {
|
|
dailyProfit = profit / days
|
|
monthlyProfit = dailyProfit * 30
|
|
calculatedAnnualRate = ((product.currentNetValue / product.principal) ** (365 / days) - 1) * 100
|
|
averageAnnualProfit = profit * (365 / days)
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
...product,
|
|
profit,
|
|
dailyProfit,
|
|
monthlyProfit,
|
|
calculatedAnnualRate,
|
|
averageAnnualProfit,
|
|
}
|
|
}
|