Refactor TransactionCard component
Refactor TransactionCard component into smaller, more manageable components without changing functionality.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { ArrowDownIcon, Coffee, Home, Car } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import TransactionEditDialog from './TransactionEditDialog';
|
||||
import TransactionIcon from './transaction/TransactionIcon';
|
||||
import TransactionDetails from './transaction/TransactionDetails';
|
||||
import TransactionAmount from './transaction/TransactionAmount';
|
||||
|
||||
export type Transaction = {
|
||||
id: string;
|
||||
@@ -13,12 +15,6 @@ export type Transaction = {
|
||||
type: 'expense' | 'income';
|
||||
};
|
||||
|
||||
const categoryIcons: Record<string, React.ReactNode> = {
|
||||
식비: <Coffee size={18} />,
|
||||
생활비: <Home size={18} />,
|
||||
교통비: <Car size={18} />,
|
||||
};
|
||||
|
||||
interface TransactionCardProps {
|
||||
transaction: Transaction;
|
||||
onUpdate?: (updatedTransaction: Transaction) => void;
|
||||
@@ -31,12 +27,6 @@ const TransactionCard: React.FC<TransactionCardProps> = ({
|
||||
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
|
||||
const { title, amount, date, category, type } = transaction;
|
||||
|
||||
const formattedAmount = new Intl.NumberFormat('ko-KR', {
|
||||
style: 'currency',
|
||||
currency: 'KRW',
|
||||
maximumFractionDigits: 0
|
||||
}).format(amount);
|
||||
|
||||
const handleSaveTransaction = (updatedTransaction: Transaction) => {
|
||||
if (onUpdate) {
|
||||
onUpdate(updatedTransaction);
|
||||
@@ -51,22 +41,11 @@ const TransactionCard: React.FC<TransactionCardProps> = ({
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="p-2 rounded-full bg-neuro-income/10 text-neuro-income">
|
||||
{categoryIcons[category] || <Coffee size={18} />}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-medium">{title}</h3>
|
||||
<p className="text-xs text-gray-500">{date}</p>
|
||||
</div>
|
||||
<TransactionIcon category={category} />
|
||||
<TransactionDetails title={title} date={date} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1">
|
||||
<ArrowDownIcon size={12} className="text-neuro-income" />
|
||||
<span className="font-medium text-neuro-income">
|
||||
{formattedAmount}
|
||||
</span>
|
||||
</div>
|
||||
<TransactionAmount amount={amount} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ import { Form } from '@/components/ui/form';
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
import TransactionFormFields, {
|
||||
transactionFormSchema,
|
||||
formatWithCommas
|
||||
formatWithCommas,
|
||||
TransactionFormValues
|
||||
} from './transaction/TransactionFormFields';
|
||||
import TransactionDeleteAlert from './transaction/TransactionDeleteAlert';
|
||||
|
||||
@@ -35,16 +36,16 @@ const TransactionEditDialog: React.FC<TransactionEditDialogProps> = ({
|
||||
onSave,
|
||||
onDelete
|
||||
}) => {
|
||||
const form = useForm({
|
||||
const form = useForm<TransactionFormValues>({
|
||||
resolver: zodResolver(transactionFormSchema),
|
||||
defaultValues: {
|
||||
title: transaction.title,
|
||||
amount: formatWithCommas(transaction.amount.toString()),
|
||||
category: transaction.category as any,
|
||||
category: transaction.category as '식비' | '생활비' | '교통비',
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = (values: any) => {
|
||||
const handleSubmit = (values: TransactionFormValues) => {
|
||||
// Remove commas from amount string and convert to number
|
||||
const cleanAmount = values.amount.replace(/,/g, '');
|
||||
|
||||
|
||||
26
src/components/transaction/TransactionAmount.tsx
Normal file
26
src/components/transaction/TransactionAmount.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
import React from 'react';
|
||||
import { ArrowDownIcon } from 'lucide-react';
|
||||
|
||||
interface TransactionAmountProps {
|
||||
amount: number;
|
||||
}
|
||||
|
||||
const TransactionAmount: React.FC<TransactionAmountProps> = ({ amount }) => {
|
||||
const formattedAmount = new Intl.NumberFormat('ko-KR', {
|
||||
style: 'currency',
|
||||
currency: 'KRW',
|
||||
maximumFractionDigits: 0
|
||||
}).format(amount);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<ArrowDownIcon size={12} className="text-neuro-income" />
|
||||
<span className="font-medium text-neuro-income">
|
||||
{formattedAmount}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TransactionAmount;
|
||||
18
src/components/transaction/TransactionDetails.tsx
Normal file
18
src/components/transaction/TransactionDetails.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
interface TransactionDetailsProps {
|
||||
title: string;
|
||||
date: string;
|
||||
}
|
||||
|
||||
const TransactionDetails: React.FC<TransactionDetailsProps> = ({ title, date }) => {
|
||||
return (
|
||||
<div>
|
||||
<h3 className="text-sm font-medium">{title}</h3>
|
||||
<p className="text-xs text-gray-500">{date}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TransactionDetails;
|
||||
23
src/components/transaction/TransactionIcon.tsx
Normal file
23
src/components/transaction/TransactionIcon.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Coffee, Home, Car } from 'lucide-react';
|
||||
|
||||
export const categoryIcons: Record<string, React.ReactNode> = {
|
||||
식비: <Coffee size={18} />,
|
||||
생활비: <Home size={18} />,
|
||||
교통비: <Car size={18} />,
|
||||
};
|
||||
|
||||
interface TransactionIconProps {
|
||||
category: string;
|
||||
}
|
||||
|
||||
const TransactionIcon: React.FC<TransactionIconProps> = ({ category }) => {
|
||||
return (
|
||||
<div className="p-2 rounded-full bg-neuro-income/10 text-neuro-income">
|
||||
{categoryIcons[category] || <Coffee size={18} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TransactionIcon;
|
||||
Reference in New Issue
Block a user