Implement code changes

The prompt asked to implement code changes.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-18 07:49:51 +00:00
parent 8e609519ac
commit 612cd37b1d
11 changed files with 444 additions and 352 deletions

View File

@@ -1,5 +1,5 @@
import React from 'react';
import React, { useState, useEffect, useRef } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { Transaction } from '@/components/TransactionCard';
@@ -32,6 +32,9 @@ interface TransactionEditDialogProps {
onDelete?: (id: string) => Promise<boolean> | boolean;
}
/**
* 트랜잭션 편집 다이얼로그 - 안정성 및 UX 개선 버전
*/
const TransactionEditDialog: React.FC<TransactionEditDialogProps> = ({
transaction,
open,
@@ -40,9 +43,13 @@ const TransactionEditDialog: React.FC<TransactionEditDialogProps> = ({
onDelete
}) => {
const { updateTransaction, deleteTransaction } = useBudget();
const isMobile = useIsMobile();
const [isSubmitting, setIsSubmitting] = useState(false);
// 작업 중첩 방지를 위한 참조
const isProcessingRef = useRef(false);
// 폼 설정
const form = useForm<TransactionFormValues>({
resolver: zodResolver(transactionFormSchema),
defaultValues: {
@@ -51,46 +58,86 @@ const TransactionEditDialog: React.FC<TransactionEditDialogProps> = ({
category: transaction.category as '식비' | '생활비' | '교통비',
},
});
const handleSubmit = (values: TransactionFormValues) => {
// Remove commas from amount string and convert to number
const cleanAmount = values.amount.replace(/,/g, '');
const updatedTransaction = {
...transaction,
title: values.title,
amount: Number(cleanAmount),
category: values.category,
};
// 컨텍스트를 통해 트랜잭션 업데이트
updateTransaction(updatedTransaction);
// 부모 컴포넌트의 onSave 콜백이 있다면 호출
if (onSave) {
onSave(updatedTransaction);
// 다이얼로그가 열릴 때 폼 값 초기화
useEffect(() => {
if (open) {
form.reset({
title: transaction.title,
amount: formatWithCommas(transaction.amount.toString()),
category: transaction.category as '식비' | '생활비' | '교통비',
});
}
}, [open, transaction, form]);
// 저장 처리 함수
const handleSubmit = async (values: TransactionFormValues) => {
// 중복 제출 방지
if (isProcessingRef.current) return;
isProcessingRef.current = true;
setIsSubmitting(true);
onOpenChange(false);
toast({
title: "지출이 수정되었습니다",
description: `${values.title} 항목이 ${formatWithCommas(cleanAmount)}원으로 수정되었습니다.`,
});
try {
// 쉼표 제거 및 숫자로 변환
const cleanAmount = values.amount.replace(/,/g, '');
const updatedTransaction = {
...transaction,
title: values.title,
amount: Number(cleanAmount),
category: values.category,
};
// 컨텍스트를 통해 트랜잭션 업데이트
updateTransaction(updatedTransaction);
// 부모 컴포넌트의 onSave 콜백이 있다면 호출
if (onSave) {
onSave(updatedTransaction);
}
// 다이얼로그 닫기
onOpenChange(false);
// 토스트 메시지
toast({
title: "지출이 수정되었습니다",
description: `${values.title} 항목이 ${formatWithCommas(cleanAmount)}원으로 수정되었습니다.`,
});
} catch (error) {
console.error('트랜잭션 업데이트 오류:', error);
toast({
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 콜백이 있다면 호출
// 부모 컴포넌트의 onDelete 콜백이 있다면 호출
if (onDelete) {
return await onDelete(transaction.id);
const result = await onDelete(transaction.id);
isProcessingRef.current = false;
return result;
}
// 부모 컴포넌트에서 처리하지 않은 경우 기본 처리
deleteTransaction(transaction.id);
isProcessingRef.current = false;
return true;
} catch (error) {
console.error('트랜잭션 삭제 중 오류:', error);
@@ -99,12 +146,17 @@ const TransactionEditDialog: React.FC<TransactionEditDialogProps> = ({
description: "지출 항목을 삭제하는데 문제가 발생했습니다.",
variant: "destructive"
});
isProcessingRef.current = false;
return false;
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<Dialog open={open} onOpenChange={(newOpen) => {
// 제출 중이면 닫기 방지
if (isSubmitting && !newOpen) return;
onOpenChange(newOpen);
}}>
<DialogContent className={`sm:max-w-md mx-auto ${isMobile ? 'rounded-xl overflow-hidden' : ''}`}>
<DialogHeader>
<DialogTitle> </DialogTitle>
@@ -121,13 +173,20 @@ const TransactionEditDialog: React.FC<TransactionEditDialogProps> = ({
<TransactionDeleteAlert onDelete={handleDelete} />
<div className="flex gap-2">
<DialogClose asChild>
<Button type="button" variant="outline"></Button>
<Button
type="button"
variant="outline"
disabled={isSubmitting}
>
</Button>
</DialogClose>
<Button
type="submit"
className="bg-neuro-income text-white hover:bg-neuro-income/90"
disabled={isSubmitting}
>
{isSubmitting ? '저장 중...' : '저장'}
</Button>
</div>
</DialogFooter>