Investments.js

import React, { useState, useContext, useEffect, useMemo } from 'react'; import { FinanceContext } from '../contexts/FinanceContext'; import { Line } from 'react-chartjs-2'; import { Chart as ChartJS, LineElement, PointElement, LinearScale, TimeScale, Tooltip, Legend } from 'chart.js'; import 'chartjs-adapter-date-fns'; // For date handling in Chart.js // Debug imports console.log('FinanceContext:', FinanceContext); // Register Chart.js components ChartJS.register(LineElement, PointElement, LinearScale, TimeScale, Tooltip, Legend); function Investments() { const context = useContext(FinanceContext); console.log('FinanceContext data:', context); const { allocations = {} } = context || {}; const [isDarkMode, setIsDarkMode] = useState(false); const [investmentAmount, setInvestmentAmount] = useState(''); const [investmentHistory, setInvestmentHistory] = useState( JSON.parse(localStorage.getItem('investmentHistory')) || [] ); const [bitcoinPrice, setBitcoinPrice] = useState( parseFloat(localStorage.getItem('bitcoinPrice')) || 117783.89 // Fallback to CoinMarketCap price (July 13, 2025) ); const [bitcoinPriceData, setBitcoinPriceData] = useState( JSON.parse(localStorage.getItem('bitcoinPriceData')) || [] ); const [riskWarning, setRiskWarning] = useState(''); // Tính ngân sách đầu tư (15% Đầu tư bản thân + 10% Dự phòng linh hoạt) const investmentBudget = parseFloat(allocations.selfInvestment || 0) + parseFloat(allocations.emergency || 0); const totalPortfolio = parseFloat(allocations.essentials || 0) + parseFloat(allocations.savings || 0) + parseFloat(allocations.selfInvestment || 0) + parseFloat(allocations.charity || 0) + parseFloat(allocations.emergency || 0); // Fetch real-time Bitcoin price and 7-day historical data from CoinGecko useEffect(() => { const fetchBitcoinData = async () => { try { // Fetch current price const priceResponse = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd'); const priceData = await priceResponse.json(); const currentPrice = priceData.bitcoin.usd; setBitcoinPrice(currentPrice); localStorage.setItem('bitcoinPrice', currentPrice); // Fetch 7-day historical data const historyResponse = await fetch('https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=7'); const historyData = await historyResponse.json(); const prices = historyData.prices.map(([timestamp, price]) => ({ date: new Date(timestamp).toISOString().split('T')[0], price, })); setBitcoinPriceData(prices); localStorage.setItem('bitcoinPriceData', JSON.stringify(prices)); } catch (error) { console.error('Error fetching Bitcoin data:', error); // Fallback to simulated data if API fails const today = new Date(); const prices = []; for (let i = 6; i >= 0; i--) { const date = new Date(today); date.setDate(today.getDate() - i); prices.push({ date: date.toISOString().split('T')[0], price: bitcoinPrice * (1 + (Math.random() - 0.5) * 0.1), // ±10% fluctuation }); } setBitcoinPriceData(prices); localStorage.setItem('bitcoinPriceData', JSON.stringify(prices)); } }; fetchBitcoinData(); // Update price every 5 minutes (300,000ms) to respect API rate limits const interval = setInterval(fetchBitcoinData, 300000); return () => clearInterval(interval); }, []); // Memoize chart data to optimize performance const chartData = useMemo(() => ({ labels: bitcoinPriceData.map((data) => data.date), datasets: [ { label: 'Giá Bitcoin (USD)', data: bitcoinPriceData.map((data) => data.price), borderColor: isDarkMode ? '#F59E0B' : '#F97316', backgroundColor: isDarkMode ? 'rgba(245, 158, 11, 0.2)' : 'rgba(249, 115, 22, 0.2)', fill: true, tension: 0.4, }, ], }), [bitcoinPriceData, isDarkMode]); const chartOptions = { scales: { x: { type: 'time', time: { unit: 'day' }, title: { display: true, text: 'Ngày', color: isDarkMode ? '#FFFFFF' : '#1F2937' }, }, y: { title: { display: true, text: 'Giá (USD)', color: isDarkMode ? '#FFFFFF' : '#1F2937' }, }, }, plugins: { legend: { labels: { color: isDarkMode ? '#FFFFFF' : '#1F2937' }, }, tooltip: { callbacks: { label: function (context) { return `Giá: $${context.raw.toFixed(2)}`; }, }, }, }, maintainAspectRatio: false, responsive: true, }; const formatVND = (value) => { const num = parseFloat(value) || 0; return new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND' }).format(num); }; const handleInvest = () => { const amount = parseFloat(investmentAmount); if (!amount || amount <= 0) { setRiskWarning('Vui lòng nhập số tiền hợp lệ.'); return; } if (amount > investmentBudget) { setRiskWarning(`Số tiền vượt quá ngân sách đầu tư (${formatVND(investmentBudget)}).`); return; } if ((amount / totalPortfolio) > 0.1) { setRiskWarning('Cảnh báo: Đầu tư Bitcoin ETF nên chiếm dưới 10% tổng danh mục để giảm rủi ro.'); } else { setRiskWarning(''); } const newInvestment = { amount, date: new Date().toLocaleString('vi-VN'), price: bitcoinPrice, type: 'Mua Bitcoin ETF (IBIT)', }; const updatedHistory = [...investmentHistory, newInvestment]; setInvestmentHistory(updatedHistory); localStorage.setItem('investmentHistory', JSON.stringify(updatedHistory)); setInvestmentAmount(''); }; const handleSell = (index) => { const updatedHistory = investmentHistory.filter((_, i) => i !== index); setInvestmentHistory(updatedHistory); localStorage.setItem('investmentHistory', JSON.stringify(updatedHistory)); setRiskWarning(''); }; // Tính lợi nhuận/tổn thất const calculateProfitLoss = (investment) => { const currentValue = (investment.amount / investment.price) * bitcoinPrice; return currentValue - investment.amount; }; return (

Đầu tư

Ngân sách đầu tư

{formatVND(investmentBudget)}

Đầu tư bản thân (15%) + Dự phòng linh hoạt (10%)

Giá Bitcoin hiện tại

${bitcoinPrice.toFixed(2)}

Xu hướng giá Bitcoin (7 ngày)

Đầu tư Bitcoin ETF

setInvestmentAmount(e.target.value)} className={`w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 transition ${isDarkMode ? 'bg-gray-800 text-white border-gray-600' : 'bg-white text-gray-800 border-gray-300'}`} placeholder="Nhập số tiền (VND)" />
{riskWarning && (

{riskWarning}

)}

Lịch sử giao dịch đầu tư

{investmentHistory.length > 0 ? (
{investmentHistory.map((investment, index) => (

Loại: {investment.type}

Số tiền: {formatVND(investment.amount)}

Giá Bitcoin lúc mua: ${investment.price.toFixed(2)}

Lợi nhuận/Tổn thất: = 0 ? 'text-green-500' : 'text-red-500'}> {formatVND(calculateProfitLoss(investment))}

Thời gian: {investment.date}

))}
) : (

Chưa có giao dịch đầu tư.

)}
); } export default Investments;
Huyền

Một Blog Anime chia sẻ những bộ anime hay download về để xem chất lượng cao nhất. neyuhv.blogspot.com does not host any files, it merely links to 3rd party services. Legal issues should be taken up with the file hosts and providers. neyuhv.blogspot.com is not responsible for any media files shown by the video providers.

Mới hơn Cũ hơn