Visual edit in Lovable
Edited UI in Lovable
This commit is contained in:
@@ -12,10 +12,13 @@ import PeriodSelector from '@/components/analytics/PeriodSelector';
|
|||||||
import SummaryCards from '@/components/analytics/SummaryCards';
|
import SummaryCards from '@/components/analytics/SummaryCards';
|
||||||
import MonthlyComparisonChart from '@/components/analytics/MonthlyComparisonChart';
|
import MonthlyComparisonChart from '@/components/analytics/MonthlyComparisonChart';
|
||||||
import CategorySpendingList from '@/components/analytics/CategorySpendingList';
|
import CategorySpendingList from '@/components/analytics/CategorySpendingList';
|
||||||
|
|
||||||
const Analytics = () => {
|
const Analytics = () => {
|
||||||
const [selectedPeriod, setSelectedPeriod] = useState('이번 달');
|
const [selectedPeriod, setSelectedPeriod] = useState('이번 달');
|
||||||
const { budgetData, getCategorySpending, transactions } = useBudget();
|
const {
|
||||||
|
budgetData,
|
||||||
|
getCategorySpending,
|
||||||
|
transactions
|
||||||
|
} = useBudget();
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
||||||
const [monthlyData, setMonthlyData] = useState<any[]>([]);
|
const [monthlyData, setMonthlyData] = useState<any[]>([]);
|
||||||
@@ -26,7 +29,7 @@ const Analytics = () => {
|
|||||||
if (document.visibilityState === 'visible') {
|
if (document.visibilityState === 'visible') {
|
||||||
console.log('분석 페이지 보임 - 데이터 새로고침');
|
console.log('분석 페이지 보임 - 데이터 새로고침');
|
||||||
setRefreshTrigger(prev => prev + 1);
|
setRefreshTrigger(prev => prev + 1);
|
||||||
|
|
||||||
// 이벤트 발생시켜 데이터 새로고침
|
// 이벤트 발생시켜 데이터 새로고침
|
||||||
try {
|
try {
|
||||||
window.dispatchEvent(new Event('storage'));
|
window.dispatchEvent(new Event('storage'));
|
||||||
@@ -38,11 +41,10 @@ const Analytics = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFocus = () => {
|
const handleFocus = () => {
|
||||||
console.log('분석 페이지 포커스 - 데이터 새로고침');
|
console.log('분석 페이지 포커스 - 데이터 새로고침');
|
||||||
setRefreshTrigger(prev => prev + 1);
|
setRefreshTrigger(prev => prev + 1);
|
||||||
|
|
||||||
// 이벤트 발생시켜 데이터 새로고침
|
// 이벤트 발생시켜 데이터 새로고침
|
||||||
try {
|
try {
|
||||||
window.dispatchEvent(new Event('storage'));
|
window.dispatchEvent(new Event('storage'));
|
||||||
@@ -53,16 +55,14 @@ const Analytics = () => {
|
|||||||
console.error('이벤트 발생 오류:', e);
|
console.error('이벤트 발생 오류:', e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||||
window.addEventListener('focus', handleFocus);
|
window.addEventListener('focus', handleFocus);
|
||||||
window.addEventListener('transactionUpdated', () => setRefreshTrigger(prev => prev + 1));
|
window.addEventListener('transactionUpdated', () => setRefreshTrigger(prev => prev + 1));
|
||||||
window.addEventListener('budgetDataUpdated', () => setRefreshTrigger(prev => prev + 1));
|
window.addEventListener('budgetDataUpdated', () => setRefreshTrigger(prev => prev + 1));
|
||||||
window.addEventListener('categoryBudgetsUpdated', () => setRefreshTrigger(prev => prev + 1));
|
window.addEventListener('categoryBudgetsUpdated', () => setRefreshTrigger(prev => prev + 1));
|
||||||
|
|
||||||
// 컴포넌트 마운트 시 초기 데이터 로드 이벤트 트리거
|
// 컴포넌트 마운트 시 초기 데이터 로드 이벤트 트리거
|
||||||
handleFocus();
|
handleFocus();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||||
window.removeEventListener('focus', handleFocus);
|
window.removeEventListener('focus', handleFocus);
|
||||||
@@ -71,13 +71,13 @@ const Analytics = () => {
|
|||||||
window.removeEventListener('categoryBudgetsUpdated', () => {});
|
window.removeEventListener('categoryBudgetsUpdated', () => {});
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 실제 예산 및 지출 데이터 사용
|
// 실제 예산 및 지출 데이터 사용
|
||||||
const totalBudget = budgetData?.monthly?.targetAmount || 0;
|
const totalBudget = budgetData?.monthly?.targetAmount || 0;
|
||||||
const totalExpense = budgetData?.monthly?.spentAmount || 0;
|
const totalExpense = budgetData?.monthly?.spentAmount || 0;
|
||||||
const savings = Math.max(0, totalBudget - totalExpense);
|
const savings = Math.max(0, totalBudget - totalExpense);
|
||||||
const savingsPercentage = totalBudget > 0 ? Math.round(savings / totalBudget * 100) : 0;
|
const savingsPercentage = totalBudget > 0 ? Math.round(savings / totalBudget * 100) : 0;
|
||||||
|
|
||||||
// 카테고리별 지출 차트 데이터 생성 - 색상 유틸리티 사용
|
// 카테고리별 지출 차트 데이터 생성 - 색상 유틸리티 사용
|
||||||
const categorySpending = getCategorySpending();
|
const categorySpending = getCategorySpending();
|
||||||
const expenseData = categorySpending.map(category => ({
|
const expenseData = categorySpending.map(category => ({
|
||||||
@@ -88,88 +88,67 @@ const Analytics = () => {
|
|||||||
|
|
||||||
// 월별 데이터 생성 - 샘플 데이터 제거하고 현재 달만 실제 데이터 사용
|
// 월별 데이터 생성 - 샘플 데이터 제거하고 현재 달만 실제 데이터 사용
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Analytics 페이지: 월별 데이터 생성', { totalBudget, totalExpense });
|
console.log('Analytics 페이지: 월별 데이터 생성', {
|
||||||
|
totalBudget,
|
||||||
|
totalExpense
|
||||||
|
});
|
||||||
|
|
||||||
// 현재 월 가져오기
|
// 현재 월 가져오기
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const currentMonth = today.getMonth();
|
const currentMonth = today.getMonth();
|
||||||
|
|
||||||
// 현재 달만 실제 데이터 사용하는 배열 생성
|
// 현재 달만 실제 데이터 사용하는 배열 생성
|
||||||
const monthlyDataArray = [{
|
const monthlyDataArray = [{
|
||||||
name: MONTHS_KR[currentMonth].split(' ')[0], // '8월' 형식으로 변환
|
name: MONTHS_KR[currentMonth].split(' ')[0],
|
||||||
|
// '8월' 형식으로 변환
|
||||||
budget: totalBudget,
|
budget: totalBudget,
|
||||||
expense: totalExpense
|
expense: totalExpense
|
||||||
}];
|
}];
|
||||||
|
|
||||||
setMonthlyData(monthlyDataArray);
|
setMonthlyData(monthlyDataArray);
|
||||||
console.log('Analytics 페이지: 월별 데이터 생성 완료', monthlyDataArray);
|
console.log('Analytics 페이지: 월별 데이터 생성 완료', monthlyDataArray);
|
||||||
}, [totalBudget, totalExpense, refreshTrigger]);
|
}, [totalBudget, totalExpense, refreshTrigger]);
|
||||||
|
|
||||||
// 이전/다음 기간 이동 처리
|
// 이전/다음 기간 이동 처리
|
||||||
const handlePrevPeriod = () => {
|
const handlePrevPeriod = () => {
|
||||||
console.log('이전 기간으로 이동');
|
console.log('이전 기간으로 이동');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNextPeriod = () => {
|
const handleNextPeriod = () => {
|
||||||
console.log('다음 기간으로 이동');
|
console.log('다음 기간으로 이동');
|
||||||
};
|
};
|
||||||
|
return <div className="min-h-screen bg-neuro-background pb-24">
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-neuro-background pb-24">
|
|
||||||
<div className="max-w-md mx-auto px-6">
|
<div className="max-w-md mx-auto px-6">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<header className="py-8 w-full">
|
<header className="py-8 w-full">
|
||||||
<h1 className="text-2xl font-bold neuro-text mb-5">지출 분석</h1>
|
<h1 className="font-bold neuro-text mb-5 text-xl">지출 분석</h1>
|
||||||
|
|
||||||
{/* Period Selector */}
|
{/* Period Selector */}
|
||||||
<PeriodSelector
|
<PeriodSelector selectedPeriod={selectedPeriod} onPrevPeriod={handlePrevPeriod} onNextPeriod={handleNextPeriod} />
|
||||||
selectedPeriod={selectedPeriod}
|
|
||||||
onPrevPeriod={handlePrevPeriod}
|
|
||||||
onNextPeriod={handleNextPeriod}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Summary Cards */}
|
{/* Summary Cards */}
|
||||||
<SummaryCards
|
<SummaryCards totalBudget={totalBudget} totalExpense={totalExpense} savingsPercentage={savingsPercentage} />
|
||||||
totalBudget={totalBudget}
|
|
||||||
totalExpense={totalExpense}
|
|
||||||
savingsPercentage={savingsPercentage}
|
|
||||||
/>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Monthly Comparison Chart */}
|
{/* Monthly Comparison Chart */}
|
||||||
<div className="mb-8 w-full">
|
<div className="mb-8 w-full">
|
||||||
<h2 className="text-lg font-semibold mb-3">월별 그래프</h2>
|
<h2 className="text-lg font-semibold mb-3">월별 그래프</h2>
|
||||||
<MonthlyComparisonChart
|
<MonthlyComparisonChart monthlyData={monthlyData} isEmpty={totalBudget === 0 && totalExpense === 0} />
|
||||||
monthlyData={monthlyData}
|
|
||||||
isEmpty={totalBudget === 0 && totalExpense === 0}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Category Pie Chart */}
|
{/* Category Pie Chart */}
|
||||||
<h2 className="text-lg font-semibold mb-3">카테고리별 지출</h2>
|
<h2 className="text-lg font-semibold mb-3">카테고리별 지출</h2>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{expenseData.some(item => item.value > 0) ? (
|
{expenseData.some(item => item.value > 0) ? <ExpenseChart data={expenseData} /> : <div className="neuro-card h-52 w-full flex items-center justify-center text-gray-400">
|
||||||
<ExpenseChart data={expenseData} />
|
|
||||||
) : (
|
|
||||||
<div className="neuro-card h-52 w-full flex items-center justify-center text-gray-400">
|
|
||||||
<p>데이터가 없습니다</p>
|
<p>데이터가 없습니다</p>
|
||||||
</div>
|
</div>}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Top Spending Categories */}
|
{/* Top Spending Categories */}
|
||||||
<h2 className="text-lg font-semibold mb-3 mt-6">주요 지출 카테고리</h2>
|
<h2 className="text-lg font-semibold mb-3 mt-6">주요 지출 카테고리</h2>
|
||||||
<CategorySpendingList
|
<CategorySpendingList categories={categorySpending} totalExpense={totalExpense} className="mb-[50px]" />
|
||||||
categories={categorySpending}
|
|
||||||
totalExpense={totalExpense}
|
|
||||||
className="mb-[50px]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AddTransactionButton />
|
<AddTransactionButton />
|
||||||
<NavBar />
|
<NavBar />
|
||||||
</div>
|
</div>;
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
export default Analytics;
|
||||||
export default Analytics;
|
|
||||||
Reference in New Issue
Block a user