Add "기타" category
Adds "기타" category to the existing categories.
This commit is contained in:
@@ -24,7 +24,7 @@ const ExpenseForm: React.FC<ExpenseFormProps> = ({ onSubmit, onCancel, isSubmitt
|
|||||||
defaultValues: {
|
defaultValues: {
|
||||||
title: '',
|
title: '',
|
||||||
amount: '',
|
amount: '',
|
||||||
category: '식비',
|
category: '음식',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import { UseFormReturn } from 'react-hook-form';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { categoryIcons, EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
|
import { categoryIcons, EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
|
||||||
|
|
||||||
// Form schema for validation - 카테고리를 3개로 제한
|
// Form schema for validation - 카테고리를 4개로 확장
|
||||||
export const transactionFormSchema = z.object({
|
export const transactionFormSchema = z.object({
|
||||||
title: z.string().min(1, '제목을 입력해주세요'),
|
title: z.string().min(1, '제목을 입력해주세요'),
|
||||||
amount: z.string().min(1, '금액을 입력해주세요'),
|
amount: z.string().min(1, '금액을 입력해주세요'),
|
||||||
category: z.enum(['음식', '쇼핑', '교통비']),
|
category: z.enum(['음식', '쇼핑', '교통비', '기타']),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TransactionFormValues = z.infer<typeof transactionFormSchema>;
|
export type TransactionFormValues = z.infer<typeof transactionFormSchema>;
|
||||||
@@ -40,7 +40,7 @@ const TransactionFormFields: React.FC<TransactionFormFieldsProps> = ({ form }) =
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>카테고리</FormLabel>
|
<FormLabel>카테고리</FormLabel>
|
||||||
<div className="grid grid-cols-3 gap-2">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
{EXPENSE_CATEGORIES.map((category) => (
|
{EXPENSE_CATEGORIES.map((category) => (
|
||||||
<div
|
<div
|
||||||
key={category}
|
key={category}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Coffee } from 'lucide-react';
|
import { Coffee, Package } from 'lucide-react';
|
||||||
import { categoryIcons } from '@/constants/categoryIcons';
|
import { categoryIcons } from '@/constants/categoryIcons';
|
||||||
|
|
||||||
interface TransactionIconProps {
|
interface TransactionIconProps {
|
||||||
@@ -8,8 +8,8 @@ interface TransactionIconProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TransactionIcon: React.FC<TransactionIconProps> = ({ category }) => {
|
const TransactionIcon: React.FC<TransactionIconProps> = ({ category }) => {
|
||||||
// 카테고리에 해당하는 아이콘이 없을 경우 기본값으로 Coffee 아이콘 사용
|
// 카테고리에 해당하는 아이콘이 없을 경우 기본값으로 Package 아이콘 사용
|
||||||
const icon = categoryIcons[category] || <Coffee size={18} />;
|
const icon = categoryIcons[category] || <Package size={18} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-2 rounded-full bg-neuro-income/10 text-neuro-income">
|
<div className="p-2 rounded-full bg-neuro-income/10 text-neuro-income">
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
|
|||||||
/**
|
/**
|
||||||
* 카테고리 매핑 함수 - 이전 카테고리명을 새 카테고리명으로 변환
|
* 카테고리 매핑 함수 - 이전 카테고리명을 새 카테고리명으로 변환
|
||||||
*/
|
*/
|
||||||
export const mapCategoryToNew = (oldCategory: string): "음식" | "쇼핑" | "교통비" => {
|
export const mapCategoryToNew = (oldCategory: string): "음식" | "쇼핑" | "교통비" | "기타" => {
|
||||||
if (oldCategory === '식비') return '음식';
|
if (oldCategory === '식비') return '음식';
|
||||||
if (oldCategory === '생활비') return '쇼핑';
|
if (oldCategory === '생활비') return '쇼핑';
|
||||||
if (EXPENSE_CATEGORIES.includes(oldCategory as any)) return oldCategory as "음식" | "쇼핑" | "교통비";
|
if (EXPENSE_CATEGORIES.includes(oldCategory as any)) return oldCategory as "음식" | "쇼핑" | "교통비" | "기타";
|
||||||
// 기본값은 '쇼핑'으로 설정
|
// 기본값은 '기타'로 설정
|
||||||
return '쇼핑';
|
return '기타';
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Coffee, Home, Car, Banknote } from 'lucide-react';
|
import { Coffee, Home, Car, Package } from 'lucide-react';
|
||||||
|
|
||||||
// 카테고리와 아이콘 매핑 정의
|
// 카테고리와 아이콘 매핑 정의
|
||||||
export const categoryIcons: Record<string, React.ReactNode> = {
|
export const categoryIcons: Record<string, React.ReactNode> = {
|
||||||
음식: <Coffee size={18} />,
|
음식: <Coffee size={18} />,
|
||||||
쇼핑: <Home size={18} />,
|
쇼핑: <Home size={18} />,
|
||||||
교통비: <Car size={18} />,
|
교통비: <Car size={18} />,
|
||||||
|
기타: <Package size={18} />,
|
||||||
수입: <Banknote size={18} />,
|
수입: <Banknote size={18} />,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 지출 카테고리 목록 - 3개로 제한
|
// 지출 카테고리 목록 - 4개로 확장
|
||||||
export const EXPENSE_CATEGORIES = ['음식', '쇼핑', '교통비'];
|
export const EXPENSE_CATEGORIES = ['음식', '쇼핑', '교통비', '기타'];
|
||||||
|
|
||||||
// 카테고리 부가 설명 정의
|
// 카테고리 부가 설명 정의
|
||||||
export const CATEGORY_DESCRIPTIONS: Record<string, string> = {
|
export const CATEGORY_DESCRIPTIONS: Record<string, string> = {
|
||||||
음식: '(식비, 음료)',
|
음식: '(식비, 음료)',
|
||||||
쇼핑: '',
|
쇼핑: '',
|
||||||
교통비: '(차량 유지비)',
|
교통비: '(차량 유지비)',
|
||||||
|
기타: '(기타 지출)',
|
||||||
식비: '(식비, 음료)', // 이전 이름과의 호환성 유지
|
식비: '(식비, 음료)', // 이전 이름과의 호환성 유지
|
||||||
생활비: '', // 이전 이름과의 호환성 유지
|
생활비: '', // 이전 이름과의 호환성 유지
|
||||||
};
|
};
|
||||||
@@ -26,8 +28,9 @@ export const CATEGORY_DESCRIPTIONS: Record<string, string> = {
|
|||||||
export const DEFAULT_CATEGORY_BUDGETS = {
|
export const DEFAULT_CATEGORY_BUDGETS = {
|
||||||
음식: 400000,
|
음식: 400000,
|
||||||
쇼핑: 600000,
|
쇼핑: 600000,
|
||||||
교통비: 200000
|
교통비: 200000,
|
||||||
|
기타: 100000
|
||||||
};
|
};
|
||||||
|
|
||||||
// 기본 월간 예산
|
// 기본 월간 예산
|
||||||
export const DEFAULT_MONTHLY_BUDGET = 1200000;
|
export const DEFAULT_MONTHLY_BUDGET = 1300000;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const loadCategoryBudgetsFromStorage = (): Record<string, number> => {
|
|||||||
const parsed = JSON.parse(storedCategoryBudgets);
|
const parsed = JSON.parse(storedCategoryBudgets);
|
||||||
console.log('카테고리 예산 로드 완료:', parsed);
|
console.log('카테고리 예산 로드 완료:', parsed);
|
||||||
|
|
||||||
// 3개 카테고리만 유지
|
// 4개 카테고리만 유지
|
||||||
const filteredBudgets: Record<string, number> = {};
|
const filteredBudgets: Record<string, number> = {};
|
||||||
EXPENSE_CATEGORIES.forEach(category => {
|
EXPENSE_CATEGORIES.forEach(category => {
|
||||||
// 이전 카테고리명이 있을 경우 새 카테고리명으로 값 이전
|
// 이전 카테고리명이 있을 경우 새 카테고리명으로 값 이전
|
||||||
@@ -36,7 +36,7 @@ export const loadCategoryBudgetsFromStorage = (): Record<string, number> => {
|
|||||||
const parsedBackup = JSON.parse(backupCategoryBudgets);
|
const parsedBackup = JSON.parse(backupCategoryBudgets);
|
||||||
console.log('백업에서 카테고리 예산 복구:', parsedBackup);
|
console.log('백업에서 카테고리 예산 복구:', parsedBackup);
|
||||||
|
|
||||||
// 3개 카테고리만 유지
|
// 4개 카테고리만 유지
|
||||||
const filteredBudgets: Record<string, number> = {};
|
const filteredBudgets: Record<string, number> = {};
|
||||||
EXPENSE_CATEGORIES.forEach(category => {
|
EXPENSE_CATEGORIES.forEach(category => {
|
||||||
// 이전 카테고리명이 있을 경우 새 카테고리명으로 값 이전
|
// 이전 카테고리명이 있을 경우 새 카테고리명으로 값 이전
|
||||||
@@ -83,7 +83,7 @@ export const saveCategoryBudgetsToStorage = (categoryBudgets: Record<string, num
|
|||||||
console.error('이전 카테고리 예산 비교 오류:', e);
|
console.error('이전 카테고리 예산 비교 오류:', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3개 카테고리만 유지하고 나머지는 제거
|
// 4개 카테고리만 유지하고 나머지는 제거
|
||||||
const filteredBudgets: Record<string, number> = {};
|
const filteredBudgets: Record<string, number> = {};
|
||||||
EXPENSE_CATEGORIES.forEach(category => {
|
EXPENSE_CATEGORIES.forEach(category => {
|
||||||
filteredBudgets[category] = categoryBudgets[category] || 0;
|
filteredBudgets[category] = categoryBudgets[category] || 0;
|
||||||
@@ -136,7 +136,7 @@ export const clearAllCategoryBudgets = (): void => {
|
|||||||
localStorage.removeItem('categoryBudgets');
|
localStorage.removeItem('categoryBudgets');
|
||||||
localStorage.removeItem('categoryBudgets_backup');
|
localStorage.removeItem('categoryBudgets_backup');
|
||||||
|
|
||||||
// 기본값으로 재설정 (3개 카테고리만)
|
// 기본값으로 재설정 (4개 카테고리만)
|
||||||
const dataString = JSON.stringify(DEFAULT_CATEGORY_BUDGETS);
|
const dataString = JSON.stringify(DEFAULT_CATEGORY_BUDGETS);
|
||||||
localStorage.setItem('categoryBudgets', dataString);
|
localStorage.setItem('categoryBudgets', dataString);
|
||||||
localStorage.setItem('categoryBudgets_backup', dataString);
|
localStorage.setItem('categoryBudgets_backup', dataString);
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ export const getCategoryColor = (category: string): string => {
|
|||||||
return '#AED581'; // 연한 녹색 (쇼핑/생활비)
|
return '#AED581'; // 연한 녹색 (쇼핑/생활비)
|
||||||
} else if (normalizedCategory.includes('교통')) {
|
} else if (normalizedCategory.includes('교통')) {
|
||||||
return '#2E7D32'; // 진한 녹색 (교통비)
|
return '#2E7D32'; // 진한 녹색 (교통비)
|
||||||
|
} else if (normalizedCategory.includes('기타')) {
|
||||||
|
return '#9E9E9E'; // 회색 (기타)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 기본 색상
|
// 기본 색상
|
||||||
|
|||||||
Reference in New Issue
Block a user