feat: Add CI/CD pipeline and code quality improvements

- Add GitHub Actions workflow for automated CI/CD
- Configure Node.js 18.x and 20.x matrix testing
- Add TypeScript type checking step
- Add ESLint code quality checks with enhanced rules
- Add Prettier formatting verification
- Add production build validation
- Upload build artifacts for deployment
- Set up automated testing on push/PR
- Replace console.log with environment-aware logger
- Add pre-commit hooks for code quality
- Exclude archive folder from linting

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
hansoo
2025-07-12 15:27:54 +09:00
parent 6a208d6b06
commit 9851627ff1
411 changed files with 14458 additions and 8680 deletions

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import BudgetTabContent from './BudgetTabContent';
import { BudgetPeriod, BudgetData } from '@/contexts/budget/types';
import React, { useEffect, useState } from "react";
import { logger } from "@/utils/logger";
import BudgetTabContent from "./BudgetTabContent";
import { BudgetPeriod, BudgetData } from "@/contexts/budget/types";
interface BudgetProgressCardProps {
budgetData: BudgetData;
@@ -9,7 +9,11 @@ interface BudgetProgressCardProps {
setSelectedTab: (value: string) => void;
formatCurrency: (amount: number) => string;
calculatePercentage: (spent: number, target: number) => number;
onSaveBudget: (type: BudgetPeriod, amount: number, newCategoryBudgets?: Record<string, number>) => void;
onSaveBudget: (
type: BudgetPeriod,
amount: number,
newCategoryBudgets?: Record<string, number>
) => void;
}
const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
@@ -18,57 +22,63 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
setSelectedTab,
formatCurrency,
calculatePercentage,
onSaveBudget
onSaveBudget,
}) => {
// 데이터 상태 추적 (불일치 감지를 위한 로컬 상태)
const [localBudgetData, setLocalBudgetData] = useState(budgetData);
// 컴포넌트 마운트 및 budgetData 변경 시 업데이트
useEffect(() => {
console.log("BudgetProgressCard 데이터 업데이트 - 예산 데이터:", budgetData);
console.log("월간 예산:", budgetData.monthly.targetAmount);
logger.info(
"BudgetProgressCard 데이터 업데이트 - 예산 데이터:",
budgetData
);
logger.info("월간 예산:", budgetData.monthly.targetAmount);
setLocalBudgetData(budgetData);
// 지연 작업으로 이벤트 발생 (컴포넌트 마운트 후 데이터 갱신)
const timeoutId = setTimeout(() => {
window.dispatchEvent(new Event('budgetDataUpdated'));
window.dispatchEvent(new Event("budgetDataUpdated"));
}, 300);
return () => clearTimeout(timeoutId);
}, [budgetData]);
// 초기 탭 설정을 위한 효과
useEffect(() => {
if (!selectedTab || selectedTab !== "monthly") {
console.log("초기 탭 설정: monthly");
setSelectedTab('monthly');
logger.info("초기 탭 설정: monthly");
setSelectedTab("monthly");
}
}, []);
// budgetDataUpdated 이벤트 감지
useEffect(() => {
const handleBudgetDataUpdated = () => {
console.log("BudgetProgressCard: 예산 데이터 업데이트 이벤트 감지");
logger.info("BudgetProgressCard: 예산 데이터 업데이트 이벤트 감지");
};
window.addEventListener('budgetDataUpdated', handleBudgetDataUpdated);
return () => window.removeEventListener('budgetDataUpdated', handleBudgetDataUpdated);
window.addEventListener("budgetDataUpdated", handleBudgetDataUpdated);
return () =>
window.removeEventListener("budgetDataUpdated", handleBudgetDataUpdated);
}, []);
// 월간 예산 설정 여부 계산
const isMonthlyBudgetSet = budgetData.monthly.targetAmount > 0;
console.log(`BudgetProgressCard 상태: 월=${isMonthlyBudgetSet}`);
logger.info(`BudgetProgressCard 상태: 월=${isMonthlyBudgetSet}`);
return (
<div className="neuro-card mb-6 overflow-hidden w-full">
<div className="text-sm text-gray-600 mb-2 px-3 pt-3"> / </div>
<BudgetTabContent
data={budgetData.monthly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount, categoryBudgets) => onSaveBudget('monthly', amount, categoryBudgets)}
<BudgetTabContent
data={budgetData.monthly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount, categoryBudgets) =>
onSaveBudget("monthly", amount, categoryBudgets)
}
/>
</div>
);