Refactor title suggestion logic

Implement new logic for title suggestions based on usage frequency.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-22 13:12:52 +00:00
parent 3229913bde
commit 74f7282fac
3 changed files with 82 additions and 161 deletions

View File

@@ -1,138 +1,56 @@
import { useState, useRef, useEffect } from 'react';
import { UseFormReturn, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useState } from 'react';
import { Transaction } from '@/contexts/budget/types';
import { useBudget } from '@/contexts/budget/BudgetContext';
import { toast } from '@/components/ui/use-toast';
import { TransactionFormValues, transactionFormSchema, formatWithCommas } from './TransactionFormFields';
import { mapCategoryToNew } from './categoryUtils';
import { toast } from '@/hooks/useToast.wrapper';
import { manageTitleSuggestions } from '@/utils/userTitlePreferences'; // 새로운 제목 관리 가져오기
/**
* 트랜잭션 편집 커스텀 훅 - 상태 및 핸들러 로직 분리
*/
export const useTransactionEdit = (
transaction: Transaction,
open: boolean,
onOpenChange: (open: boolean) => void,
onSave?: (updatedTransaction: Transaction) => void,
onDelete?: (id: string) => Promise<boolean> | boolean,
onClose: () => void
) => {
const { updateTransaction, deleteTransaction } = useBudget();
const [isSubmitting, setIsSubmitting] = useState(false);
// 작업 중첩 방지를 위한 참조
const isProcessingRef = useRef(false);
// 폼 설정
const form = useForm<TransactionFormValues>({
resolver: zodResolver(transactionFormSchema),
defaultValues: {
title: transaction.title,
amount: formatWithCommas(transaction.amount.toString()),
category: mapCategoryToNew(transaction.category),
paymentMethod: transaction.paymentMethod || '신용카드', // 지출 방법 추가, 기본값은 신용카드
},
});
// 다이얼로그가 열릴 때 폼 값 초기화
useEffect(() => {
if (open) {
form.reset({
title: transaction.title,
amount: formatWithCommas(transaction.amount.toString()),
category: mapCategoryToNew(transaction.category),
paymentMethod: transaction.paymentMethod || '신용카드', // 지출 방법 기본값
});
}
}, [open, transaction, form]);
const { updateTransaction } = useBudget();
// 저장 처리 함수
const handleSubmit = async (values: TransactionFormValues) => {
// 중복 제출 방지
if (isProcessingRef.current) return;
isProcessingRef.current = true;
setIsSubmitting(true);
const handleSubmit = (updatedTransaction: Transaction) => {
try {
// 쉼표 제거 및 숫자로 변환
const cleanAmount = values.amount.replace(/,/g, '');
setIsSubmitting(true);
const updatedTransaction = {
...transaction,
title: values.title,
amount: Number(cleanAmount),
category: values.category,
paymentMethod: values.paymentMethod, // 지출 방법 업데이트
};
// 컨텍스트를 통해 트랜잭션 업데이트
// 트랜잭션 업데이트
updateTransaction(updatedTransaction);
// 부모 컴포넌트의 onSave 콜백이 있다면 호출
if (onSave) {
onSave(updatedTransaction);
// 지출일 경우 제목 관리 로직 실행
if (updatedTransaction.type === 'expense') {
manageTitleSuggestions(updatedTransaction);
}
// 다이얼로그 닫기
onOpenChange(false);
// 토스트 메시지
// 성공 메시지 표시
toast({
title: "지출이 수정되었습니다",
description: `${values.title} 항목이 ${formatWithCommas(cleanAmount)}원으로 수정되었습니다.`,
title: "거래 내역이 업데이트되었습니다",
description: `${updatedTransaction.title} 항목이 수정되었습니다.`,
});
// 이벤트 발생 처리
window.dispatchEvent(new CustomEvent('transactionChanged', {
detail: { type: 'update', transaction: updatedTransaction }
}));
// 다이얼로그 닫기
onClose();
} catch (error) {
console.error('트랜잭션 업데이트 오류:', error);
console.error('거래 내역 업데이트 오류 발생:', error);
toast({
title: "저장 실패",
description: "지출 항목을 저장하는데 문제가 발생했습니다.",
title: "거래 내역 업데이트 실패",
description: "내역을 업데이트하는 도중 오류가 발생했습니다.",
variant: "destructive"
});
} finally {
// 상태 초기화
setIsSubmitting(false);
isProcessingRef.current = false;
}
};
// 삭제 처리 함수
const handleDelete = async (): Promise<boolean> => {
// 중복 처리 방지
if (isProcessingRef.current) return false;
isProcessingRef.current = true;
try {
// 다이얼로그 닫기를 먼저 수행 (UI 블로킹 방지)
onOpenChange(false);
// 부모 컴포넌트의 onDelete 콜백이 있다면 호출
if (onDelete) {
const result = await onDelete(transaction.id);
isProcessingRef.current = false;
return result;
}
// 부모 컴포넌트에서 처리하지 않은 경우 기본 처리
deleteTransaction(transaction.id);
isProcessingRef.current = false;
return true;
} catch (error) {
console.error('트랜잭션 삭제 중 오류:', error);
toast({
title: "삭제 실패",
description: "지출 항목을 삭제하는데 문제가 발생했습니다.",
variant: "destructive"
});
isProcessingRef.current = false;
return false;
}
};
return {
form,
isSubmitting,
handleSubmit,
handleDelete
handleSubmit
};
};