diff --git a/android/version.properties b/android/version.properties index cbe5865..8599a1c 100644 --- a/android/version.properties +++ b/android/version.properties @@ -1,4 +1,6 @@ + #Tue Mar 18 00:16:17 KST 2025 buildNumber=2 versionCode=1 -versionName=1.0.2 +versionName=1.0.1 + diff --git a/build-apk.sh b/build-apk.sh index c5819d9..615d2a5 100755 --- a/build-apk.sh +++ b/build-apk.sh @@ -12,56 +12,8 @@ NC='\033[0m' # No Color # 프로젝트 디렉토리로 이동 cd "$(dirname "$0")" -# 버전 정보 파일 경로 -VERSION_PROPS_FILE="android/version.properties" - -# 현재 버전 정보 읽기 -if [ -f "$VERSION_PROPS_FILE" ]; then - CURRENT_VERSION_NAME=$(grep "versionName" "$VERSION_PROPS_FILE" | cut -d'=' -f2) - CURRENT_VERSION_CODE=$(grep "versionCode" "$VERSION_PROPS_FILE" | cut -d'=' -f2) - CURRENT_BUILD_NUMBER=$(grep "buildNumber" "$VERSION_PROPS_FILE" | cut -d'=' -f2) - - echo -e "${YELLOW}현재 버전 정보:${NC}" - echo -e "버전 이름: ${GREEN}$CURRENT_VERSION_NAME${NC}" - echo -e "버전 코드: ${GREEN}$CURRENT_VERSION_CODE${NC}" - echo -e "빌드 번호: ${GREEN}$CURRENT_BUILD_NUMBER${NC}" - - # 버전 수정 여부 확인 - echo -e "\n${YELLOW}버전 정보를 수정하시겠습니까? (y/n)${NC}" - read -r UPDATE_VERSION - - if [[ "$UPDATE_VERSION" == "y" || "$UPDATE_VERSION" == "Y" ]]; then - echo -e "\n${YELLOW}새 버전 이름을 입력하세요 (현재: $CURRENT_VERSION_NAME):${NC}" - read -r NEW_VERSION_NAME - - if [ -z "$NEW_VERSION_NAME" ]; then - NEW_VERSION_NAME=$CURRENT_VERSION_NAME - fi - - echo -e "${YELLOW}새 버전 코드를 입력하세요 (현재: $CURRENT_VERSION_CODE):${NC}" - read -r NEW_VERSION_CODE - - if [ -z "$NEW_VERSION_CODE" ]; then - NEW_VERSION_CODE=$CURRENT_VERSION_CODE - fi - - # 버전 정보 업데이트 - sed -i '' "s/versionName=$CURRENT_VERSION_NAME/versionName=$NEW_VERSION_NAME/g" "$VERSION_PROPS_FILE" - sed -i '' "s/versionCode=$CURRENT_VERSION_CODE/versionCode=$NEW_VERSION_CODE/g" "$VERSION_PROPS_FILE" - - echo -e "\n${GREEN}버전 정보가 업데이트되었습니다:${NC}" - echo -e "버전 이름: ${GREEN}$NEW_VERSION_NAME${NC}" - echo -e "버전 코드: ${GREEN}$NEW_VERSION_CODE${NC}" - else - echo -e "${YELLOW}현재 버전 정보를 유지합니다.${NC}" - fi -else - echo -e "${RED}버전 정보 파일을 찾을 수 없습니다: $VERSION_PROPS_FILE${NC}" - exit 1 -fi - # 빌드 타입 선택 메뉴 -echo -e "\n${YELLOW}Zellyy Finance 앱 빌드 스크립트${NC}" +echo -e "${YELLOW}Zellyy Finance 앱 빌드 스크립트${NC}" echo -e "${YELLOW}=============================${NC}" echo -e "빌드 타입을 선택하세요:" echo -e "1) 디버그 빌드 (개발 및 테스트용)" @@ -179,15 +131,15 @@ if [ "$BUILD_TYPE" = "debug" ]; then fi APK_PATH="app/build/outputs/apk/debug/app-debug.apk" - DEST_PATH="$HOME/Dev/zellyy-finance-debug.apk" + DEST_PATH="$HOME/zellyy-finance-debug.apk" if [ -f "$APK_PATH" ]; then echo -e "${GREEN}디버그 APK 빌드 성공!${NC}" echo -e "APK 파일 위치: $(pwd)/$APK_PATH" - # Dev 디렉토리로 APK 복사 + # 홈 디렉토리로 APK 복사 cp "$APK_PATH" "$DEST_PATH" - echo -e "${GREEN}APK를 Dev 디렉토리에 복사했습니다: $DEST_PATH${NC}" + echo -e "${GREEN}APK를 홈 디렉토리에 복사했습니다: $DEST_PATH${NC}" # 연결된 기기 확인 DEVICES=$(adb devices | grep -v "List" | grep "device" | wc -l) @@ -227,15 +179,15 @@ elif [ "$BUILD_TYPE" = "release-aab" ]; then fi AAB_PATH="app/build/outputs/bundle/release/app-release.aab" - DEST_PATH="$HOME/Dev/zellyy-finance-release.aab" + DEST_PATH="$HOME/zellyy-finance-release.aab" if [ -f "$AAB_PATH" ]; then echo -e "${GREEN}릴리즈 AAB 빌드 성공!${NC}" echo -e "AAB 파일 위치: $(pwd)/$AAB_PATH" - # Dev 디렉토리로 AAB 복사 + # 홈 디렉토리로 AAB 복사 cp "$AAB_PATH" "$DEST_PATH" - echo -e "${GREEN}AAB를 Dev 디렉토리에 복사했습니다: $DEST_PATH${NC}" + echo -e "${GREEN}AAB를 홈 디렉토리에 복사했습니다: $DEST_PATH${NC}" echo -e "${YELLOW}다음 단계:${NC}" echo "1. Google Play Console에 AAB 파일 업로드: $DEST_PATH" @@ -255,15 +207,15 @@ elif [ "$BUILD_TYPE" = "release-apk" ]; then fi SIGNED_APK_PATH="app/build/outputs/apk/release/app-release.apk" - DEST_PATH="$HOME/Dev/zellyy-finance-release.apk" + DEST_PATH="$HOME/zellyy-finance-release.apk" if [ -f "$SIGNED_APK_PATH" ]; then echo -e "${GREEN}서명된 릴리즈 APK 빌드 성공!${NC}" echo -e "APK 파일 위치: $(pwd)/$SIGNED_APK_PATH" - # Dev 디렉토리로 APK 복사 + # 홈 디렉토리로 APK 복사 cp "$SIGNED_APK_PATH" "$DEST_PATH" - echo -e "${GREEN}서명된 APK를 Dev 디렉토리에 복사했습니다: $DEST_PATH${NC}" + echo -e "${GREEN}서명된 APK를 홈 디렉토리에 복사했습니다: $DEST_PATH${NC}" # 연결된 기기 확인 DEVICES=$(adb devices | grep -v "List" | grep "device" | wc -l) diff --git a/build-ios.sh b/build-ios.sh old mode 100755 new mode 100644 index cabcbd5..533c62a --- a/build-ios.sh +++ b/build-ios.sh @@ -12,55 +12,8 @@ NC='\033[0m' # No Color # 프로젝트 디렉토리로 이동 cd "$(dirname "$0")" -# 프로젝트 파일 경로 -XCODEPROJ_FILE="ios/App/App.xcodeproj/project.pbxproj" - -# 현재 버전 및 빌드 번호 가져오기 -if [ -f "$XCODEPROJ_FILE" ]; then - MARKETING_VERSION=$(grep -A 1 "MARKETING_VERSION" "$XCODEPROJ_FILE" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1) - CURRENT_PROJECT_VERSION=$(grep -A 1 "CURRENT_PROJECT_VERSION" "$XCODEPROJ_FILE" | grep -o '[0-9]\+' | head -1) - - echo -e "${YELLOW}현재 버전 정보:${NC}" - echo -e "마케팅 버전: ${GREEN}$MARKETING_VERSION${NC}" - echo -e "빌드 번호: ${GREEN}$CURRENT_PROJECT_VERSION${NC}" - - # 버전 수정 여부 확인 - echo -e "\n${YELLOW}버전 정보를 수정하시겠습니까? (y/n)${NC}" - read -r UPDATE_VERSION - - if [[ "$UPDATE_VERSION" == "y" || "$UPDATE_VERSION" == "Y" ]]; then - echo -e "\n${YELLOW}새 마케팅 버전을 입력하세요 (현재: $MARKETING_VERSION):${NC}" - read -r NEW_MARKETING_VERSION - - if [ -z "$NEW_MARKETING_VERSION" ]; then - NEW_MARKETING_VERSION=$MARKETING_VERSION - fi - - echo -e "${YELLOW}새 빌드 번호를 입력하세요 (현재: $CURRENT_PROJECT_VERSION):${NC}" - read -r NEW_PROJECT_VERSION - - if [ -z "$NEW_PROJECT_VERSION" ]; then - NEW_PROJECT_VERSION=$CURRENT_PROJECT_VERSION - fi - - # 버전 정보 업데이트 - # macOS에서는 sed -i에 백업 확장자를 지정해야 함 - sed -i '' "s/MARKETING_VERSION = $MARKETING_VERSION;/MARKETING_VERSION = $NEW_MARKETING_VERSION;/g" "$XCODEPROJ_FILE" - sed -i '' "s/CURRENT_PROJECT_VERSION = $CURRENT_PROJECT_VERSION;/CURRENT_PROJECT_VERSION = $NEW_PROJECT_VERSION;/g" "$XCODEPROJ_FILE" - - echo -e "\n${GREEN}버전 정보가 업데이트되었습니다:${NC}" - echo -e "마케팅 버전: ${GREEN}$NEW_MARKETING_VERSION${NC}" - echo -e "빌드 번호: ${GREEN}$NEW_PROJECT_VERSION${NC}" - else - echo -e "${YELLOW}현재 버전 정보를 유지합니다.${NC}" - fi -else - echo -e "${RED}프로젝트 파일을 찾을 수 없습니다: $XCODEPROJ_FILE${NC}" - exit 1 -fi - # 빌드 타입 선택 메뉴 -echo -e "\n${YELLOW}Zellyy Finance iOS 앱 빌드 스크립트${NC}" +echo -e "${YELLOW}Zellyy Finance iOS 앱 빌드 스크립트${NC}" echo -e "${YELLOW}=============================${NC}" echo -e "빌드 타입을 선택하세요:" echo -e "1) 디버그 빌드 (개발 및 테스트용)" @@ -307,9 +260,9 @@ EOF echo -e "${GREEN}디버그용 IPA 파일 생성 성공!${NC}" echo -e "IPA 파일 위치: $(pwd)/$DEBUG_IPA_PATH" - # Dev 디렉토리로 IPA 복사 + # 홈 디렉토리로 IPA 복사 cp "$DEBUG_IPA_PATH" "$DEBUG_DEST_PATH" - echo -e "${GREEN}IPA를 Dev 디렉토리에 복사했습니다: $DEBUG_DEST_PATH${NC}" + echo -e "${GREEN}IPA를 홈 디렉토리에 복사했습니다: $DEBUG_DEST_PATH${NC}" echo -e "${YELLOW}다음 방법으로 다른 기기에 설치할 수 있습니다:${NC}" echo "1. Apple Configurator 2 앱 사용" @@ -362,9 +315,9 @@ elif [ "$BUILD_TYPE" = "release" ]; then echo -e "${GREEN}IPA 파일 생성 성공!${NC}" echo -e "IPA 파일 위치: $(pwd)/$IPA_PATH" - # Dev 디렉토리로 IPA 복사 + # 홈 디렉토리로 IPA 복사 cp "$IPA_PATH" "$DEST_PATH" - echo -e "${GREEN}IPA를 Dev 디렉토리에 복사했습니다: $DEST_PATH${NC}" + echo -e "${GREEN}IPA를 홈 디렉토리에 복사했습니다: $DEST_PATH${NC}" echo -e "${YELLOW}다음 단계:${NC}" echo "1. App Store Connect에 로그인: https://appstoreconnect.apple.com" diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 8dd6931..e3b76f0 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -13,7 +13,7 @@ interface BudgetData { remainingAmount: number; } -export interface BudgetTabContentProps { +interface BudgetTabContentProps { data: BudgetData; formatCurrency: (amount: number) => string; calculatePercentage: (spent: number, target: number) => number; @@ -26,12 +26,6 @@ const BudgetTabContent: React.FC = ({ calculatePercentage, onSaveBudget }) => { - // 데이터 유효성 체크 - 데이터가 없으면 기본값 사용 - if (!data) { - console.warn('BudgetTabContent: data prop이 제공되지 않았습니다. 기본값을 사용합니다.'); - data = { targetAmount: 0, spentAmount: 0, remainingAmount: 0 }; - } - const { categoryBudgets, showBudgetInput, diff --git a/src/components/RecentTransactionsSection.tsx b/src/components/RecentTransactionsSection.tsx index c37fa18..8366610 100644 --- a/src/components/RecentTransactionsSection.tsx +++ b/src/components/RecentTransactionsSection.tsx @@ -1,4 +1,3 @@ - import React from 'react'; import { Transaction } from '@/contexts/budget/types'; import TransactionEditDialog from './TransactionEditDialog'; @@ -9,7 +8,7 @@ import { useRecentTransactions } from '@/hooks/transactions/useRecentTransaction import { useRecentTransactionsDialog } from '@/hooks/transactions/useRecentTransactionsDialog'; import RecentTransactionItem from './recent-transactions/RecentTransactionItem'; -export interface RecentTransactionsSectionProps { +interface RecentTransactionsSectionProps { transactions: Transaction[]; onUpdateTransaction?: (transaction: Transaction) => void; } diff --git a/src/components/SafeAreaContainer.tsx b/src/components/SafeAreaContainer.tsx index 45f764b..78f2b47 100644 --- a/src/components/SafeAreaContainer.tsx +++ b/src/components/SafeAreaContainer.tsx @@ -12,7 +12,6 @@ interface SafeAreaContainerProps { /** * 플랫폼별 안전 영역(Safe Area)을 고려한 컨테이너 컴포넌트 * iOS에서는 노치/다이나믹 아일랜드를 고려한 여백 적용 - * CSS 변수와 env() 함수를 사용하여 정확한 안전 영역 계산 */ const SafeAreaContainer: React.FC = ({ children, @@ -25,24 +24,17 @@ const SafeAreaContainer: React.FC = ({ // 마운트 시 플랫폼 확인 useEffect(() => { setIsIOS(isIOSPlatform()); - - // iOS 디버깅용 로그 - if (isIOSPlatform()) { - console.info('iOS 플랫폼 감지됨 - 안전 영역 적용'); - } }, []); // 플랫폼에 따른 클래스 결정 let safeAreaClass = ''; if (isIOS) { - safeAreaClass = 'ios-safe-area'; - - if (bottomOnly) safeAreaClass += ' ios-safe-area-bottom-only'; - if (topOnly) safeAreaClass += ' ios-safe-area-top-only'; + if (!bottomOnly) safeAreaClass += ' pt-12'; // iOS 상단 안전 영역 + if (!topOnly) safeAreaClass += ' pb-8'; // iOS 하단 안전 영역 } else { - // 안드로이드 기본 여백 - safeAreaClass = 'android-safe-area'; + if (!bottomOnly) safeAreaClass += ' pt-4'; // 안드로이드 상단 여백 + if (!topOnly) safeAreaClass += ' pb-4'; // 안드로이드 하단 여백 } return ( diff --git a/src/components/SafeAreaDebug.tsx b/src/components/SafeAreaDebug.tsx deleted file mode 100644 index 90a5b5c..0000000 --- a/src/components/SafeAreaDebug.tsx +++ /dev/null @@ -1,51 +0,0 @@ - -import React, { useEffect, useState } from 'react'; -import { isIOSPlatform } from '@/utils/platform'; - -/** - * 안전 영역(Safe Area) 디버그 컴포넌트 - * 노치나 다이나믹 아일랜드 등 iOS 기기의 안전 영역을 시각적으로 표시 - */ -const SafeAreaDebug = () => { - const [isIOS, setIsIOS] = useState(false); - const [safeAreaTop, setSafeAreaTop] = useState('0px'); - const [safeAreaBottom, setSafeAreaBottom] = useState('0px'); - - useEffect(() => { - setIsIOS(isIOSPlatform()); - - // iOS에서만 안전 영역 값 가져오기 시도 - if (isIOSPlatform()) { - // CSS 변수에서 값 가져오기 시도 - const computedStyle = getComputedStyle(document.documentElement); - const topInset = computedStyle.getPropertyValue('--safe-area-top') || - computedStyle.getPropertyValue('env(safe-area-inset-top)') || - '0px'; - - const bottomInset = computedStyle.getPropertyValue('--safe-area-bottom') || - computedStyle.getPropertyValue('env(safe-area-inset-bottom)') || - '0px'; - - setSafeAreaTop(topInset); - setSafeAreaBottom(bottomInset); - - console.info('iOS 안전 영역 감지:', { - top: topInset, - bottom: bottomInset - }); - } - }, []); - - if (!isIOS) { - return null; // iOS가 아니면 렌더링하지 않음 - } - - return ( -
-
Safe Area Top: {safeAreaTop}
-
Safe Area Bottom: {safeAreaBottom}
-
- ); -}; - -export default SafeAreaDebug; diff --git a/src/hooks/budget/useBudgetTabContent.ts b/src/hooks/budget/useBudgetTabContent.ts index 6fd20d7..04580cd 100644 --- a/src/hooks/budget/useBudgetTabContent.ts +++ b/src/hooks/budget/useBudgetTabContent.ts @@ -37,18 +37,15 @@ export const useBudgetTabContent = ({ calculatePercentage, onSaveBudget }: UseBudgetTabContentProps): UseBudgetTabContentReturn => { - // 데이터가 undefined인 경우를 방지하기 위한 기본값 설정 - const safeData = data || { targetAmount: 0, spentAmount: 0, remainingAmount: 0 }; - const [categoryBudgets, setCategoryBudgets] = useState>({}); const [showBudgetInput, setShowBudgetInput] = useState(false); - const spentAmount = safeData.spentAmount; - const targetAmount = safeData.targetAmount; + const spentAmount = data.spentAmount; + const targetAmount = data.targetAmount; // 로그 추가 - 받은 데이터 확인 useEffect(() => { - console.log(`BudgetTabContent 수신 데이터:`, safeData); - }, [safeData]); + console.log(`BudgetTabContent 수신 데이터:`, data); + }, [data]); // 전역 예산 데이터가 변경되었을 때 로컬 상태 갱신 useEffect(() => { diff --git a/src/index.css b/src/index.css index e9175ce..6b4e9a2 100644 --- a/src/index.css +++ b/src/index.css @@ -150,28 +150,7 @@ @apply neuro-pressed px-4 py-3 w-full focus:outline-none focus:ring-2 focus:ring-neuro-accent/30; } - /* 안전 영역 관련 개선된 클래스 */ - .ios-safe-area { - padding-top: max(1rem, env(safe-area-inset-top)); - padding-bottom: max(1rem, env(safe-area-inset-bottom)); - padding-left: env(safe-area-inset-left); - padding-right: env(safe-area-inset-right); - } - - .ios-safe-area-top-only { - padding-top: max(1rem, env(safe-area-inset-top)); - padding-bottom: 1rem; - } - - .ios-safe-area-bottom-only { - padding-top: 1rem; - padding-bottom: max(1rem, env(safe-area-inset-bottom)); - } - - .android-safe-area { - padding: 1rem; - } - + /* 안전 영역 관련 클래스 */ .has-safe-area-top { padding-top: max(1rem, env(safe-area-inset-top)); } @@ -289,16 +268,6 @@ --safe-area-bottom: env(safe-area-inset-bottom); padding-bottom: var(--safe-area-bottom); } - - /* iOS 안전 영역 디버깅 클래스 */ - .debug-safe-areas { - --safe-area-top-color: rgba(255, 0, 0, 0.2); - --safe-area-bottom-color: rgba(0, 0, 255, 0.2); - - background: - linear-gradient(to bottom, var(--safe-area-top-color) 0, var(--safe-area-top-color) env(safe-area-inset-top), transparent env(safe-area-inset-top)), - linear-gradient(to top, var(--safe-area-bottom-color) 0, var(--safe-area-bottom-color) env(safe-area-inset-bottom), transparent env(safe-area-inset-bottom)); - } } .font-inter { diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index f652db0..8f62b5f 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -1,65 +1,174 @@ import React, { useEffect } from 'react'; -import NavBar from '../components/NavBar'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import BudgetTabContent from '@/components/BudgetTabContent'; -import RecentTransactionsSection from '@/components/RecentTransactionsSection'; +import NavBar from '@/components/NavBar'; +import AddTransactionButton from '@/components/AddTransactionButton'; import Header from '@/components/Header'; -import { useBudget } from '@/contexts/budget'; -import SafeAreaContainer from '@/components/SafeAreaContainer'; -import { formatCurrency } from '@/utils/formatters'; +import WelcomeDialog from '@/components/onboarding/WelcomeDialog'; +import HomeContent from '@/components/home/HomeContent'; +import { useBudget } from '@/contexts/budget/BudgetContext'; +import { useAuth } from '@/contexts/auth'; +import { useWelcomeDialog } from '@/hooks/useWelcomeDialog'; +import { useDataInitialization } from '@/hooks/useDataInitialization'; +import { useIsMobile } from '@/hooks/use-mobile'; +import useNotifications from '@/hooks/useNotifications'; +// 메인 컴포넌트 const Index = () => { - const { transactions, budgetData, handleBudgetGoalUpdate } = useBudget(); - - // 데이터 구조 확인용 로깅 + const { + transactions, + budgetData, + selectedTab, + setSelectedTab, + handleBudgetGoalUpdate, + updateTransaction, + getCategorySpending, + resetBudgetData + } = useBudget(); + + const { user } = useAuth(); + const { showWelcome, checkWelcomeDialogState, handleCloseWelcome } = useWelcomeDialog(); + const { isInitialized } = useDataInitialization(resetBudgetData); + const isMobile = useIsMobile(); + const { addNotification } = useNotifications(); + + // 초기화 후 환영 메시지 표시 상태 확인 useEffect(() => { - console.info('Index 페이지 마운트, 현재 데이터 상태:'); - console.info('트랜잭션 수:', transactions?.length); - console.info('예산 데이터:', budgetData); - }, [transactions, budgetData]); - - // 예산 퍼센트 계산 함수 - const calculatePercentage = (spent: number, target: number) => { - if (target <= 0) return 0; - return Math.min(100, Math.round((spent / target) * 100)); - }; - + if (isInitialized) { + const timeoutId = setTimeout(checkWelcomeDialogState, 500); + return () => clearTimeout(timeoutId); + } + }, [isInitialized, checkWelcomeDialogState]); + + // 앱 시작시 예시 알림 추가 (실제 앱에서는 필요한 이벤트에 따라 알림 추가) + useEffect(() => { + // 환영 메시지가 이미 표시되었는지 확인하는 키 + const welcomeNotificationSent = sessionStorage.getItem('welcomeNotificationSent'); + + if (isInitialized && user && !welcomeNotificationSent) { + // 사용자 로그인 시 알림 예시 (한 번만 실행) + const timeoutId = setTimeout(() => { + addNotification( + '환영합니다!', + '젤리의 적자탈출에 오신 것을 환영합니다. 예산을 설정하고 지출을 기록해보세요.' + ); + // 세션 스토리지에 환영 메시지 표시 여부 저장 + sessionStorage.setItem('welcomeNotificationSent', 'true'); + }, 2000); + + return () => clearTimeout(timeoutId); + } + }, [isInitialized, user, addNotification]); + + // 페이지가 처음 로드될 때 데이터 로딩 확인 + useEffect(() => { + console.log('Index 페이지 마운트, 현재 데이터 상태:'); + console.log('트랜잭션:', transactions.length); + console.log('예산 데이터:', budgetData); + + // 페이지 마운트 시 데이터 동기화 이벤트 수동 발생 + try { + window.dispatchEvent(new Event('transactionUpdated')); + window.dispatchEvent(new Event('budgetDataUpdated')); + window.dispatchEvent(new Event('categoryBudgetsUpdated')); + } catch (e) { + console.error('이벤트 발생 오류:', e); + } + + // 백업된 데이터 복구 확인 (메인 데이터가 없는 경우만) + try { + if (!localStorage.getItem('budgetData')) { + const budgetBackup = localStorage.getItem('budgetData_backup'); + if (budgetBackup) { + console.log('예산 데이터 백업에서 복구'); + localStorage.setItem('budgetData', budgetBackup); + window.dispatchEvent(new Event('budgetDataUpdated')); + } + } + + if (!localStorage.getItem('categoryBudgets')) { + const categoryBackup = localStorage.getItem('categoryBudgets_backup'); + if (categoryBackup) { + console.log('카테고리 예산 백업에서 복구'); + localStorage.setItem('categoryBudgets', categoryBackup); + window.dispatchEvent(new Event('categoryBudgetsUpdated')); + } + } + + if (!localStorage.getItem('transactions')) { + const transactionBackup = localStorage.getItem('transactions_backup'); + if (transactionBackup) { + console.log('트랜잭션 백업에서 복구'); + localStorage.setItem('transactions', transactionBackup); + window.dispatchEvent(new Event('transactionUpdated')); + } + } + } catch (error) { + console.error('백업 복구 시도 중 오류:', error); + } + }, [transactions.length, budgetData]); + + // 앱이 포커스를 얻었을 때 데이터를 새로고침 + useEffect(() => { + const handleFocus = () => { + console.log('창이 포커스를 얻음 - 데이터 새로고침'); + // 이벤트 발생시켜 데이터 새로고침 + try { + window.dispatchEvent(new Event('storage')); + window.dispatchEvent(new Event('transactionUpdated')); + window.dispatchEvent(new Event('budgetDataUpdated')); + window.dispatchEvent(new Event('categoryBudgetsUpdated')); + } catch (e) { + console.error('이벤트 발생 오류:', e); + } + }; + + // 포커스 이벤트 + window.addEventListener('focus', handleFocus); + + // 가시성 변경 이벤트 (백그라운드에서 전경으로 돌아올 때) + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { + console.log('페이지가 다시 보임 - 데이터 새로고침'); + handleFocus(); + } + }); + + // 정기적인 데이터 새로고침 (10초마다) + const refreshInterval = setInterval(() => { + if (document.visibilityState === 'visible') { + console.log('정기 새로고침 - 데이터 업데이트'); + handleFocus(); + } + }, 10000); + + return () => { + window.removeEventListener('focus', handleFocus); + document.removeEventListener('visibilitychange', () => {}); + clearInterval(refreshInterval); + }; + }, []); + return ( - +
- - - - 예산 - 최근 거래 - - - - {budgetData && budgetData.monthly && ( - - handleBudgetGoalUpdate('monthly', amount, categoryBudgets) - } - /> - )} - - - - console.log('트랜잭션 업데이트', transaction)} - /> - - + +
- + - + + {/* 첫 사용자 안내 팝업 */} + +
); }; diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 4188dd6..1a3eb7a 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -1,3 +1,4 @@ + import React from 'react'; import { useNavigate } from 'react-router-dom'; import NavBar from '@/components/NavBar'; @@ -7,7 +8,6 @@ import { User, CreditCard, Bell, Lock, HelpCircle, LogOut, ChevronRight } from ' import { cn } from '@/lib/utils'; import { useAuth } from '@/contexts/auth'; import { useToast } from '@/hooks/useToast.wrapper'; -import SafeAreaContainer from '@/components/SafeAreaContainer'; const SettingsOption = ({ icon: Icon, @@ -57,8 +57,7 @@ const Settings = () => { navigate(path); }; - return ( - + return
{/* Header */}
@@ -122,8 +121,7 @@ const Settings = () => {
- - ); +
; }; export default Settings;