Prevent duplicate toast notifications
The application was displaying duplicate toast notifications due to events being triggered multiple times. This commit prevents duplicate notifications.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { Transaction } from '../types';
|
||||
import {
|
||||
@@ -6,11 +5,12 @@ import {
|
||||
saveTransactionsToStorage,
|
||||
clearAllTransactions
|
||||
} from '../storage';
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
import { toast } from '@/hooks/useToast.wrapper'; // 래퍼 사용
|
||||
|
||||
// 트랜잭션 상태 관리 훅
|
||||
export const useTransactionState = () => {
|
||||
const [transactions, setTransactions] = useState<Transaction[]>([]);
|
||||
const [lastDeletedId, setLastDeletedId] = useState<string | null>(null);
|
||||
|
||||
// 초기 트랜잭션 로드 및 이벤트 리스너 설정
|
||||
useEffect(() => {
|
||||
@@ -75,10 +75,20 @@ export const useTransactionState = () => {
|
||||
// 트랜잭션 삭제 함수
|
||||
const deleteTransaction = useCallback((transactionId: string) => {
|
||||
console.log('트랜잭션 삭제:', transactionId);
|
||||
|
||||
// 중복 삭제 방지
|
||||
if (lastDeletedId === transactionId) {
|
||||
console.log('중복 삭제 요청 무시:', transactionId);
|
||||
return;
|
||||
}
|
||||
|
||||
setLastDeletedId(transactionId);
|
||||
|
||||
setTransactions(prev => {
|
||||
const updated = prev.filter(transaction => transaction.id !== transactionId);
|
||||
saveTransactionsToStorage(updated);
|
||||
|
||||
// 토스트는 한 번만 호출
|
||||
toast({
|
||||
title: "지출이 삭제되었습니다",
|
||||
description: "지출 항목이 성공적으로 삭제되었습니다.",
|
||||
@@ -86,7 +96,10 @@ export const useTransactionState = () => {
|
||||
|
||||
return updated;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// 5초 후 lastDeletedId 초기화
|
||||
setTimeout(() => setLastDeletedId(null), 5000);
|
||||
}, [lastDeletedId]);
|
||||
|
||||
// 트랜잭션 초기화 함수
|
||||
const resetTransactions = useCallback(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
import { BudgetData } from '../types';
|
||||
import { getInitialBudgetData } from '../budgetUtils';
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
import { toast } from '@/hooks/useToast.wrapper'; // 래퍼 사용
|
||||
|
||||
/**
|
||||
* 예산 데이터 불러오기
|
||||
@@ -70,6 +70,19 @@ export const saveBudgetDataToStorage = (budgetData: BudgetData): void => {
|
||||
// 데이터 문자열로 변환
|
||||
const dataString = JSON.stringify(budgetData);
|
||||
|
||||
// 이전 예산과 비교하여 변경 여부 확인
|
||||
let hasChanged = true;
|
||||
try {
|
||||
const oldDataString = localStorage.getItem('budgetData');
|
||||
if (oldDataString) {
|
||||
const oldData = JSON.parse(oldDataString);
|
||||
// 월간 예산이 동일하면 변경되지 않은 것으로 판단
|
||||
hasChanged = oldData.monthly.targetAmount !== budgetData.monthly.targetAmount;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('이전 예산 비교 오류:', e);
|
||||
}
|
||||
|
||||
// 로컬 스토리지에 저장
|
||||
localStorage.setItem('budgetData', dataString);
|
||||
console.log('예산 데이터 저장 완료', budgetData);
|
||||
@@ -78,19 +91,14 @@ export const saveBudgetDataToStorage = (budgetData: BudgetData): void => {
|
||||
localStorage.setItem('budgetData_backup', dataString);
|
||||
localStorage.setItem('lastBudgetSaveTime', new Date().toISOString());
|
||||
|
||||
// 이벤트 발생
|
||||
try {
|
||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||
window.dispatchEvent(new StorageEvent('storage', {
|
||||
key: 'budgetData',
|
||||
newValue: dataString
|
||||
}));
|
||||
} catch (e) {
|
||||
console.error('이벤트 발생 오류:', e);
|
||||
}
|
||||
// 이벤트 발생 (단일 이벤트로 통합)
|
||||
const event = new CustomEvent('budgetChanged', {
|
||||
detail: { data: budgetData, hasChanged }
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
|
||||
// toast 알림
|
||||
if (budgetData.monthly.targetAmount > 0) {
|
||||
// toast 알림 (변경된 경우에만)
|
||||
if (hasChanged && budgetData.monthly.targetAmount > 0) {
|
||||
toast({
|
||||
title: "예산 저장 완료",
|
||||
description: `월 예산이 ${budgetData.monthly.targetAmount.toLocaleString()}원으로 설정되었습니다.`,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import { DEFAULT_CATEGORY_BUDGETS } from '../budgetUtils';
|
||||
import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
import { toast } from '@/hooks/useToast.wrapper'; // 래퍼 사용
|
||||
|
||||
/**
|
||||
* 카테고리 예산 불러오기
|
||||
@@ -53,6 +54,21 @@ export const loadCategoryBudgetsFromStorage = (): Record<string, number> => {
|
||||
*/
|
||||
export const saveCategoryBudgetsToStorage = (categoryBudgets: Record<string, number>): void => {
|
||||
try {
|
||||
// 이전 예산과 비교하여 변경 여부 확인
|
||||
let hasChanged = true;
|
||||
try {
|
||||
const oldDataString = localStorage.getItem('categoryBudgets');
|
||||
if (oldDataString) {
|
||||
const oldData = JSON.parse(oldDataString);
|
||||
// 총 예산이 동일하면 변경되지 않은 것으로 판단
|
||||
const oldTotal = Object.values(oldData).reduce((sum: number, val: number) => sum + val, 0);
|
||||
const newTotal = Object.values(categoryBudgets).reduce((sum: number, val: number) => sum + val, 0);
|
||||
hasChanged = oldTotal !== newTotal;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('이전 카테고리 예산 비교 오류:', e);
|
||||
}
|
||||
|
||||
// 3개 카테고리만 유지하고 나머지는 제거
|
||||
const filteredBudgets: Record<string, number> = {};
|
||||
EXPENSE_CATEGORIES.forEach(category => {
|
||||
@@ -69,23 +85,18 @@ export const saveCategoryBudgetsToStorage = (categoryBudgets: Record<string, num
|
||||
|
||||
console.log('카테고리 예산 저장 완료:', filteredBudgets);
|
||||
|
||||
// 스토리지 이벤트 수동 트리거 (동일 창에서도 감지하기 위함)
|
||||
try {
|
||||
window.dispatchEvent(new Event('categoryBudgetsUpdated'));
|
||||
window.dispatchEvent(new StorageEvent('storage', {
|
||||
key: 'categoryBudgets',
|
||||
newValue: dataString
|
||||
}));
|
||||
} catch (e) {
|
||||
console.error('이벤트 발생 오류:', e);
|
||||
}
|
||||
// 단일 이벤트로 통합
|
||||
const event = new CustomEvent('categoryBudgetsChanged', {
|
||||
detail: { data: filteredBudgets, hasChanged }
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
|
||||
// 마지막 저장 시간 기록 (데이터 검증용)
|
||||
localStorage.setItem('lastCategoryBudgetSaveTime', new Date().toISOString());
|
||||
|
||||
// 토스트 알림
|
||||
// 토스트 알림 (변경된 경우에만)
|
||||
const totalBudget = Object.values(filteredBudgets).reduce((sum, val) => sum + val, 0);
|
||||
if (totalBudget > 0) {
|
||||
if (hasChanged && totalBudget > 0) {
|
||||
toast({
|
||||
title: "카테고리 예산 저장 완료",
|
||||
description: `카테고리별 예산 총 ${totalBudget.toLocaleString()}원이 설정되었습니다.`,
|
||||
|
||||
Reference in New Issue
Block a user