expense ver 2

import React, { useState, useEffect, useContext } from 'react'; import axios from 'axios'; import { FinanceContext } from '../contexts/FinanceContext'; import ExpenseTracker from '../components/ExpenseTracker'; import numberToWords from '../utils/numberToWords'; function Expenses() { const [amount, setAmount] = useState(''); const [category, setCategory] = useState(''); const [expenses, setExpenses] = useState([]); const [error, setError] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const { allocations, allocateFunds } = useContext(FinanceContext); const [isDarkMode, setIsDarkMode] = useState(false); const token = localStorage.getItem('token'); // Lấy danh sách chi tiêu khi mount component useEffect(() => { const fetchExpenses = async () => { try { const response = await axios.get('https://backend-rockefeller-finance.onrender.com/api/expenses', { headers: { Authorization: `Bearer ${token}` }, }); setExpenses(response.data); } catch (err) { setError(err.response?.data?.error || 'Lỗi lấy chi tiêu'); } }; fetchExpenses(); }, [token]); // Xử lý submit phân bổ ngân sách (cũ) const handleSubmit = (e) => { e.preventDefault(); const parsedAmount = parseFloat(amount); if (parsedAmount <= 0) { alert('Vui lòng nhập số tiền hợp lệ!'); return; } setIsSubmitting(true); setTimeout(() => { allocateFunds(parsedAmount); setIsSubmitting(false); setAmount(''); }, 1000); }; // Xử lý thêm chi tiêu mới (tương tác backend) const handleAddExpense = async (e) => { e.preventDefault(); setError(''); if (!amount || !category) { setError('Vui lòng nhập đủ thông tin chi tiêu'); return; } try { setIsSubmitting(true); const response = await axios.post( 'https://rockefeller-finance-backend.onrender.com/api/expenses', { amount: parseFloat(amount), category }, { headers: { Authorization: `Bearer ${token}` } } ); setExpenses(response.data); setAmount(''); setCategory(''); } catch (err) { setError(err.response?.data?.error || 'Lỗi thêm chi tiêu'); } finally { setIsSubmitting(false); } }; const toggleDarkMode = () => { setIsDarkMode(!isDarkMode); }; const formatVND = (value) => { return new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND' }).format(value); }; const totalAmount = parseFloat(allocations.essentials || 0) + parseFloat(allocations.savings || 0) + parseFloat(allocations.selfInvestment || 0) + parseFloat(allocations.charity || 0) + parseFloat(allocations.emergency || 0); return (

Quản lý chi tiêu

Phân bổ ngân sách

setAmount(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" required min="1" />

Tiêu dùng thiết yếu (50%)

{formatVND(allocations.essentials)}

Tiết kiệm bắt buộc (20%)

{formatVND(allocations.savings)}

Đầu tư bản thân (15%)

{formatVND(allocations.selfInvestment)}

Từ thiện (5%)

{formatVND(allocations.charity)}

Dự phòng linh hoạt (10%)

{formatVND(allocations.emergency)}

{totalAmount > 0 && (

Tổng số tiền

{formatVND(totalAmount)}

{numberToWords(totalAmount)}

)} {/* Thêm phần form nhập chi tiêu hoàn toàn mới, quản lý trạng thái riêng */}

Thêm chi tiêu mới

{error &&

{error}

}
setAmount(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 chi tiêu" required min="0.01" step="0.01" />
setCategory(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 danh mục chi tiêu" required />

Lịch sử chi tiêu

{expenses.length === 0 ? (

Chưa có chi tiêu nào.

) : (
    {expenses.map((expense, index) => (
  • {expense.category} {expense.amount.toLocaleString('vi-VN')} VND {expense.date}
  • ))}
)}
); } export default Expenses;
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