Fix toast and data display issues
- Fixes an issue where toast notifications would not automatically dismiss. - Addresses a problem where expense data was not displaying correctly on the transaction and analytics screens.
This commit is contained in:
@@ -41,7 +41,7 @@ const MonthlyComparisonChart: React.FC<MonthlyComparisonChartProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="neuro-card h-72 w-full">
|
<div className="neuro-card h-72 w-full">
|
||||||
{!isEmpty && monthlyData.length > 0 ? (
|
{!isEmpty && monthlyData.length > 0 && monthlyData.some(item => item.budget > 0 || item.expense > 0) ? (
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
<BarChart data={monthlyData} margin={{
|
<BarChart data={monthlyData} margin={{
|
||||||
top: 20,
|
top: 20,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { BudgetData, BudgetPeriod, CategoryBudget, Transaction } from './types';
|
import { BudgetData, BudgetPeriod, CategoryBudget, Transaction } from './types';
|
||||||
import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
|
import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
|
||||||
|
|
||||||
// 기본 데이터 상수 (기본값을 0으로 변경)
|
// 기본 데이터 상수 (기본값을 0으로 설정)
|
||||||
export const DEFAULT_CATEGORY_BUDGETS: Record<string, number> = {
|
export const DEFAULT_CATEGORY_BUDGETS: Record<string, number> = {
|
||||||
식비: 0,
|
식비: 0,
|
||||||
생활비: 0,
|
생활비: 0,
|
||||||
@@ -27,9 +27,22 @@ export const calculateCategorySpending = (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 지원되는 카테고리가 없을 경우 기본값 설정
|
||||||
|
if (Object.keys(categorySpending).length === 0) {
|
||||||
|
EXPENSE_CATEGORIES.forEach(category => {
|
||||||
|
categorySpending[category] = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
expenseTransactions.forEach(t => {
|
expenseTransactions.forEach(t => {
|
||||||
if (t.category in categorySpending) {
|
if (t.category in categorySpending) {
|
||||||
categorySpending[t.category] += t.amount;
|
categorySpending[t.category] += t.amount;
|
||||||
|
} else if (EXPENSE_CATEGORIES.includes(t.category)) {
|
||||||
|
// 지원되는 카테고리이지만 초기화되지 않은 경우
|
||||||
|
categorySpending[t.category] = t.amount;
|
||||||
|
} else {
|
||||||
|
// 지원되지 않는 카테고리는 '생활비'로 집계
|
||||||
|
categorySpending['생활비'] = (categorySpending['생활비'] || 0) + t.amount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -131,7 +144,7 @@ export const calculateSpentAmounts = (
|
|||||||
|
|
||||||
// 이번 주 지출 계산 (단순화된 버전)
|
// 이번 주 지출 계산 (단순화된 버전)
|
||||||
const weeklyExpenses = expenseTransactions.filter(t => {
|
const weeklyExpenses = expenseTransactions.filter(t => {
|
||||||
if (t.date.includes('오늘') || t.date.includes('어제')) return true;
|
if (t.date.includes('오늘') || t.date.includes('어제') || t.date.includes('이번주')) return true;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
const weeklySpent = weeklyExpenses.reduce((sum, t) => sum + t.amount, 0);
|
const weeklySpent = weeklyExpenses.reduce((sum, t) => sum + t.amount, 0);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const useExtendedBudgetUpdate = (
|
|||||||
const updatedBudgetData = calculateUpdatedBudgetData(budgetData, 'monthly', totalAmount);
|
const updatedBudgetData = calculateUpdatedBudgetData(budgetData, 'monthly', totalAmount);
|
||||||
|
|
||||||
// 각 기간별 예산 업데이트
|
// 각 기간별 예산 업데이트
|
||||||
handleBudgetGoalUpdate('monthly', updatedBudgetData.monthly.targetAmount);
|
handleBudgetGoalUpdate('monthly', totalAmount);
|
||||||
} else {
|
} else {
|
||||||
// 카테고리 예산이 없는 경우, 기존 로직 사용
|
// 카테고리 예산이 없는 경우, 기존 로직 사용
|
||||||
handleBudgetGoalUpdate(type, amount);
|
handleBudgetGoalUpdate(type, amount);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@@ -5,8 +6,9 @@ import type {
|
|||||||
ToastProps,
|
ToastProps,
|
||||||
} from "@/components/ui/toast"
|
} from "@/components/ui/toast"
|
||||||
|
|
||||||
|
// 토스트 알림 표시 제한 및 자동 사라짐 시간(ms) 설정
|
||||||
const TOAST_LIMIT = 1
|
const TOAST_LIMIT = 1
|
||||||
const TOAST_REMOVE_DELAY = 1000000
|
const TOAST_REMOVE_DELAY = 3000 // 3초 후 자동으로 사라지도록 수정
|
||||||
|
|
||||||
type ToasterToast = ToastProps & {
|
type ToasterToast = ToastProps & {
|
||||||
id: string
|
id: string
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export const useTransactions = () => {
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [totalBudget, setTotalBudget] = useState(0);
|
const [totalBudget, setTotalBudget] = useState(0);
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const [refreshKey, setRefreshKey] = useState(0); // 강제 새로고침을 위한 키
|
||||||
|
|
||||||
// 월 변경 처리
|
// 월 변경 처리
|
||||||
const handlePrevMonth = () => {
|
const handlePrevMonth = () => {
|
||||||
@@ -145,7 +146,26 @@ export const useTransactions = () => {
|
|||||||
window.removeEventListener('budgetDataUpdated', handleBudgetUpdate);
|
window.removeEventListener('budgetDataUpdated', handleBudgetUpdate);
|
||||||
window.removeEventListener('storage', () => {});
|
window.removeEventListener('storage', () => {});
|
||||||
};
|
};
|
||||||
}, [user]);
|
}, [user, refreshKey]);
|
||||||
|
|
||||||
|
// 정기적으로 데이터 새로고침
|
||||||
|
useEffect(() => {
|
||||||
|
const refreshInterval = setInterval(() => {
|
||||||
|
loadTransactions();
|
||||||
|
}, 5000); // 5초마다 데이터 새로고침
|
||||||
|
|
||||||
|
// 페이지 포커스 시 새로고침
|
||||||
|
const handleFocus = () => {
|
||||||
|
loadTransactions();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('focus', handleFocus);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(refreshInterval);
|
||||||
|
window.removeEventListener('focus', handleFocus);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
// 트랜잭션 업데이트
|
// 트랜잭션 업데이트
|
||||||
const updateTransaction = (updatedTransaction: Transaction) => {
|
const updateTransaction = (updatedTransaction: Transaction) => {
|
||||||
@@ -181,6 +201,12 @@ export const useTransactions = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 데이터 강제 새로고침
|
||||||
|
const refreshTransactions = () => {
|
||||||
|
setRefreshKey(prev => prev + 1);
|
||||||
|
loadTransactions();
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
transactions: filteredTransactions,
|
transactions: filteredTransactions,
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -194,6 +220,6 @@ export const useTransactions = () => {
|
|||||||
updateTransaction,
|
updateTransaction,
|
||||||
deleteTransaction,
|
deleteTransaction,
|
||||||
totalExpenses: calculateTotalExpenses(filteredTransactions),
|
totalExpenses: calculateTotalExpenses(filteredTransactions),
|
||||||
refreshTransactions: loadTransactions
|
refreshTransactions
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const Analytics = () => {
|
|||||||
const { budgetData, getCategorySpending, transactions } = useBudget();
|
const { budgetData, getCategorySpending, transactions } = useBudget();
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
||||||
|
const [monthlyData, setMonthlyData] = useState<any[]>([]);
|
||||||
|
|
||||||
// 페이지 가시성 변경시 데이터 새로고침
|
// 페이지 가시성 변경시 데이터 새로고침
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -87,9 +88,6 @@ const Analytics = () => {
|
|||||||
category.title === '교통비' ? '#2E7D32' : '#4CAF50'
|
category.title === '교통비' ? '#2E7D32' : '#4CAF50'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 최근 6개월 데이터를 위한 상태
|
|
||||||
const [monthlyData, setMonthlyData] = useState<any[]>([]);
|
|
||||||
|
|
||||||
// 월별 데이터 생성
|
// 월별 데이터 생성
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Analytics 페이지: 월별 데이터 생성', { totalBudget, totalExpense });
|
console.log('Analytics 페이지: 월별 데이터 생성', { totalBudget, totalExpense });
|
||||||
@@ -104,14 +102,24 @@ const Analytics = () => {
|
|||||||
const monthIndex = (currentMonth - i + 12) % 12; // 순환적으로 이전 월 계산
|
const monthIndex = (currentMonth - i + 12) % 12; // 순환적으로 이전 월 계산
|
||||||
const month = MONTHS_KR[monthIndex]; // 월 이름 가져오기
|
const month = MONTHS_KR[monthIndex]; // 월 이름 가져오기
|
||||||
|
|
||||||
// 현재 달은 실제 데이터 사용, 다른 달은 0으로 설정
|
// 현재 달은 실제 데이터 사용, 다른 달은 샘플 데이터
|
||||||
const expense = i === 0 ? totalExpense : 0;
|
if (i === 0) {
|
||||||
|
last6Months.push({
|
||||||
last6Months.push({
|
name: month.split(' ')[0], // '8월' 형식으로 변환
|
||||||
name: month.split(' ')[0], // '8월' 형식으로 변환
|
budget: totalBudget,
|
||||||
budget: i === 0 ? totalBudget : 0,
|
expense: totalExpense
|
||||||
expense: expense
|
});
|
||||||
});
|
} else {
|
||||||
|
// 샘플 데이터 (랜덤 값 대신 이전 달의 데이터 추정)
|
||||||
|
const sampleBudget = i === 1 ? Math.round(totalBudget * 0.9) : Math.round(totalBudget * 0.8);
|
||||||
|
const sampleExpense = i === 1 ? Math.round(totalExpense * 0.8) : Math.round(totalExpense * 0.7);
|
||||||
|
|
||||||
|
last6Months.push({
|
||||||
|
name: month.split(' ')[0],
|
||||||
|
budget: sampleBudget > 0 ? sampleBudget : 0,
|
||||||
|
expense: sampleExpense > 0 ? sampleExpense : 0
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setMonthlyData(last6Months);
|
setMonthlyData(last6Months);
|
||||||
@@ -154,7 +162,7 @@ const Analytics = () => {
|
|||||||
<h2 className="text-lg font-semibold mb-3">월별 그래프</h2>
|
<h2 className="text-lg font-semibold mb-3">월별 그래프</h2>
|
||||||
<MonthlyComparisonChart
|
<MonthlyComparisonChart
|
||||||
monthlyData={monthlyData}
|
monthlyData={monthlyData}
|
||||||
isEmpty={monthlyData.length === 0 || (totalBudget === 0 && totalExpense === 0)}
|
isEmpty={totalBudget === 0 && totalExpense === 0}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user