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 (
{riskWarning && (
);
}
export default Investments;
Đầ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}
)}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ư.
)}