Refactor syncUtils module
Refactor the syncUtils module to improve code organization and maintainability by breaking it down into smaller, more focused utility functions.
This commit is contained in:
127
src/utils/sync/budgetSync.ts
Normal file
127
src/utils/sync/budgetSync.ts
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
import { supabase } from '@/lib/supabase';
|
||||||
|
import { isSyncEnabled } from './syncSettings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload budget data from local storage to Supabase
|
||||||
|
*/
|
||||||
|
export const uploadBudgets = async (userId: string): Promise<void> => {
|
||||||
|
if (!isSyncEnabled()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const budgetData = localStorage.getItem('budgetData');
|
||||||
|
const categoryBudgets = localStorage.getItem('categoryBudgets');
|
||||||
|
|
||||||
|
if (budgetData) {
|
||||||
|
const parsedBudgetData = JSON.parse(budgetData);
|
||||||
|
|
||||||
|
// 기존 예산 데이터 삭제
|
||||||
|
await supabase
|
||||||
|
.from('budgets')
|
||||||
|
.delete()
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
// 새 예산 데이터 삽입
|
||||||
|
const { error } = await supabase.from('budgets').insert({
|
||||||
|
user_id: userId,
|
||||||
|
daily_target: parsedBudgetData.daily.targetAmount,
|
||||||
|
weekly_target: parsedBudgetData.weekly.targetAmount,
|
||||||
|
monthly_target: parsedBudgetData.monthly.targetAmount
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categoryBudgets) {
|
||||||
|
const parsedCategoryBudgets = JSON.parse(categoryBudgets);
|
||||||
|
|
||||||
|
// 기존 카테고리 예산 삭제
|
||||||
|
await supabase
|
||||||
|
.from('category_budgets')
|
||||||
|
.delete()
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
// 카테고리별 예산 데이터 변환 및 삽입
|
||||||
|
const categoryEntries = Object.entries(parsedCategoryBudgets).map(
|
||||||
|
([category, amount]) => ({
|
||||||
|
user_id: userId,
|
||||||
|
category,
|
||||||
|
amount
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('category_budgets')
|
||||||
|
.insert(categoryEntries);
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('예산 데이터 업로드 완료');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('예산 데이터 업로드 실패:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download budget data from Supabase to local storage
|
||||||
|
*/
|
||||||
|
export const downloadBudgets = async (userId: string): Promise<void> => {
|
||||||
|
if (!isSyncEnabled()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 예산 데이터 가져오기
|
||||||
|
const { data: budgetData, error: budgetError } = await supabase
|
||||||
|
.from('budgets')
|
||||||
|
.select('*')
|
||||||
|
.eq('user_id', userId)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (budgetError && budgetError.code !== 'PGRST116') throw budgetError;
|
||||||
|
|
||||||
|
// 카테고리 예산 가져오기
|
||||||
|
const { data: categoryData, error: categoryError } = await supabase
|
||||||
|
.from('category_budgets')
|
||||||
|
.select('*')
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
if (categoryError) throw categoryError;
|
||||||
|
|
||||||
|
if (budgetData) {
|
||||||
|
// 예산 데이터 로컬 형식으로 변환
|
||||||
|
const localBudgetData = {
|
||||||
|
daily: {
|
||||||
|
targetAmount: budgetData.daily_target,
|
||||||
|
spentAmount: 0, // 지출액은 로컬에서 계산
|
||||||
|
remainingAmount: budgetData.daily_target
|
||||||
|
},
|
||||||
|
weekly: {
|
||||||
|
targetAmount: budgetData.weekly_target,
|
||||||
|
spentAmount: 0,
|
||||||
|
remainingAmount: budgetData.weekly_target
|
||||||
|
},
|
||||||
|
monthly: {
|
||||||
|
targetAmount: budgetData.monthly_target,
|
||||||
|
spentAmount: 0,
|
||||||
|
remainingAmount: budgetData.monthly_target
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
localStorage.setItem('budgetData', JSON.stringify(localBudgetData));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categoryData && categoryData.length > 0) {
|
||||||
|
// 카테고리 예산 로컬 형식으로 변환
|
||||||
|
const localCategoryBudgets = categoryData.reduce((acc, curr) => {
|
||||||
|
acc[curr.category] = curr.amount;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, number>);
|
||||||
|
|
||||||
|
localStorage.setItem('categoryBudgets', JSON.stringify(localCategoryBudgets));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('예산 데이터 다운로드 완료');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('예산 데이터 다운로드 실패:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
16
src/utils/sync/syncSettings.ts
Normal file
16
src/utils/sync/syncSettings.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
// Core synchronization settings utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if synchronization is enabled in local storage
|
||||||
|
*/
|
||||||
|
export const isSyncEnabled = (): boolean => {
|
||||||
|
return localStorage.getItem('syncEnabled') === 'true';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update synchronization settings in local storage
|
||||||
|
*/
|
||||||
|
export const setSyncEnabled = (enabled: boolean): void => {
|
||||||
|
localStorage.setItem('syncEnabled', enabled.toString());
|
||||||
|
};
|
||||||
76
src/utils/sync/transactionSync.ts
Normal file
76
src/utils/sync/transactionSync.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
import { supabase } from '@/lib/supabase';
|
||||||
|
import { Transaction } from '@/components/TransactionCard';
|
||||||
|
import { isSyncEnabled } from './syncSettings';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload transaction data from local storage to Supabase
|
||||||
|
*/
|
||||||
|
export const uploadTransactions = async (userId: string): Promise<void> => {
|
||||||
|
if (!isSyncEnabled()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const localTransactions = localStorage.getItem('transactions');
|
||||||
|
if (!localTransactions) return;
|
||||||
|
|
||||||
|
const transactions: Transaction[] = JSON.parse(localTransactions);
|
||||||
|
|
||||||
|
// 기존 데이터 삭제 후 새로 업로드
|
||||||
|
await supabase
|
||||||
|
.from('transactions')
|
||||||
|
.delete()
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
// 트랜잭션 배치 처리
|
||||||
|
const { error } = await supabase.from('transactions').insert(
|
||||||
|
transactions.map(t => ({
|
||||||
|
user_id: userId,
|
||||||
|
title: t.title,
|
||||||
|
amount: t.amount,
|
||||||
|
date: t.date,
|
||||||
|
category: t.category,
|
||||||
|
type: t.type,
|
||||||
|
transaction_id: t.id // 로컬 ID 보존
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
console.log('트랜잭션 업로드 완료');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('트랜잭션 업로드 실패:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download transaction data from Supabase to local storage
|
||||||
|
*/
|
||||||
|
export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||||
|
if (!isSyncEnabled()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from('transactions')
|
||||||
|
.select('*')
|
||||||
|
.eq('user_id', userId);
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
// Supabase 형식에서 로컬 형식으로 변환
|
||||||
|
const transactions = data.map(t => ({
|
||||||
|
id: t.transaction_id || t.id,
|
||||||
|
title: t.title,
|
||||||
|
amount: t.amount,
|
||||||
|
date: t.date,
|
||||||
|
category: t.category,
|
||||||
|
type: t.type
|
||||||
|
}));
|
||||||
|
|
||||||
|
localStorage.setItem('transactions', JSON.stringify(transactions));
|
||||||
|
console.log('트랜잭션 다운로드 완료');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('트랜잭션 다운로드 실패:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,206 +1,21 @@
|
|||||||
|
|
||||||
import { supabase } from '@/lib/supabase';
|
import { isSyncEnabled, setSyncEnabled } from './sync/syncSettings';
|
||||||
import { Transaction } from '@/components/TransactionCard';
|
import { uploadTransactions, downloadTransactions } from './sync/transactionSync';
|
||||||
|
import { uploadBudgets, downloadBudgets } from './sync/budgetSync';
|
||||||
|
|
||||||
// 동기화 상태 확인
|
// Export all utility functions to maintain the same public API
|
||||||
export const isSyncEnabled = (): boolean => {
|
export {
|
||||||
return localStorage.getItem('syncEnabled') === 'true';
|
isSyncEnabled,
|
||||||
|
setSyncEnabled,
|
||||||
|
uploadTransactions,
|
||||||
|
downloadTransactions,
|
||||||
|
uploadBudgets,
|
||||||
|
downloadBudgets
|
||||||
};
|
};
|
||||||
|
|
||||||
// 동기화 설정 변경
|
/**
|
||||||
export const setSyncEnabled = (enabled: boolean): void => {
|
* Synchronize all data with Supabase
|
||||||
localStorage.setItem('syncEnabled', enabled.toString());
|
*/
|
||||||
};
|
|
||||||
|
|
||||||
// 로컬 트랜잭션 데이터를 Supabase에 업로드
|
|
||||||
export const uploadTransactions = async (userId: string): Promise<void> => {
|
|
||||||
if (!isSyncEnabled()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const localTransactions = localStorage.getItem('transactions');
|
|
||||||
if (!localTransactions) return;
|
|
||||||
|
|
||||||
const transactions: Transaction[] = JSON.parse(localTransactions);
|
|
||||||
|
|
||||||
// 기존 데이터 삭제 후 새로 업로드
|
|
||||||
await supabase
|
|
||||||
.from('transactions')
|
|
||||||
.delete()
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
// 트랜잭션 배치 처리
|
|
||||||
const { error } = await supabase.from('transactions').insert(
|
|
||||||
transactions.map(t => ({
|
|
||||||
user_id: userId,
|
|
||||||
title: t.title,
|
|
||||||
amount: t.amount,
|
|
||||||
date: t.date,
|
|
||||||
category: t.category,
|
|
||||||
type: t.type,
|
|
||||||
transaction_id: t.id // 로컬 ID 보존
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
|
|
||||||
console.log('트랜잭션 업로드 완료');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('트랜잭션 업로드 실패:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Supabase에서 트랜잭션 데이터 다운로드
|
|
||||||
export const downloadTransactions = async (userId: string): Promise<void> => {
|
|
||||||
if (!isSyncEnabled()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('transactions')
|
|
||||||
.select('*')
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
|
|
||||||
if (data && data.length > 0) {
|
|
||||||
// Supabase 형식에서 로컬 형식으로 변환
|
|
||||||
const transactions = data.map(t => ({
|
|
||||||
id: t.transaction_id || t.id,
|
|
||||||
title: t.title,
|
|
||||||
amount: t.amount,
|
|
||||||
date: t.date,
|
|
||||||
category: t.category,
|
|
||||||
type: t.type
|
|
||||||
}));
|
|
||||||
|
|
||||||
localStorage.setItem('transactions', JSON.stringify(transactions));
|
|
||||||
console.log('트랜잭션 다운로드 완료');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('트랜잭션 다운로드 실패:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 예산 데이터 업로드
|
|
||||||
export const uploadBudgets = async (userId: string): Promise<void> => {
|
|
||||||
if (!isSyncEnabled()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const budgetData = localStorage.getItem('budgetData');
|
|
||||||
const categoryBudgets = localStorage.getItem('categoryBudgets');
|
|
||||||
|
|
||||||
if (budgetData) {
|
|
||||||
const parsedBudgetData = JSON.parse(budgetData);
|
|
||||||
|
|
||||||
// 기존 예산 데이터 삭제
|
|
||||||
await supabase
|
|
||||||
.from('budgets')
|
|
||||||
.delete()
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
// 새 예산 데이터 삽입
|
|
||||||
const { error } = await supabase.from('budgets').insert({
|
|
||||||
user_id: userId,
|
|
||||||
daily_target: parsedBudgetData.daily.targetAmount,
|
|
||||||
weekly_target: parsedBudgetData.weekly.targetAmount,
|
|
||||||
monthly_target: parsedBudgetData.monthly.targetAmount
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (categoryBudgets) {
|
|
||||||
const parsedCategoryBudgets = JSON.parse(categoryBudgets);
|
|
||||||
|
|
||||||
// 기존 카테고리 예산 삭제
|
|
||||||
await supabase
|
|
||||||
.from('category_budgets')
|
|
||||||
.delete()
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
// 카테고리별 예산 데이터 변환 및 삽입
|
|
||||||
const categoryEntries = Object.entries(parsedCategoryBudgets).map(
|
|
||||||
([category, amount]) => ({
|
|
||||||
user_id: userId,
|
|
||||||
category,
|
|
||||||
amount
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const { error } = await supabase
|
|
||||||
.from('category_budgets')
|
|
||||||
.insert(categoryEntries);
|
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('예산 데이터 업로드 완료');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('예산 데이터 업로드 실패:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 예산 데이터 다운로드
|
|
||||||
export const downloadBudgets = async (userId: string): Promise<void> => {
|
|
||||||
if (!isSyncEnabled()) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 예산 데이터 가져오기
|
|
||||||
const { data: budgetData, error: budgetError } = await supabase
|
|
||||||
.from('budgets')
|
|
||||||
.select('*')
|
|
||||||
.eq('user_id', userId)
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (budgetError && budgetError.code !== 'PGRST116') throw budgetError;
|
|
||||||
|
|
||||||
// 카테고리 예산 가져오기
|
|
||||||
const { data: categoryData, error: categoryError } = await supabase
|
|
||||||
.from('category_budgets')
|
|
||||||
.select('*')
|
|
||||||
.eq('user_id', userId);
|
|
||||||
|
|
||||||
if (categoryError) throw categoryError;
|
|
||||||
|
|
||||||
if (budgetData) {
|
|
||||||
// 예산 데이터 로컬 형식으로 변환
|
|
||||||
const localBudgetData = {
|
|
||||||
daily: {
|
|
||||||
targetAmount: budgetData.daily_target,
|
|
||||||
spentAmount: 0, // 지출액은 로컬에서 계산
|
|
||||||
remainingAmount: budgetData.daily_target
|
|
||||||
},
|
|
||||||
weekly: {
|
|
||||||
targetAmount: budgetData.weekly_target,
|
|
||||||
spentAmount: 0,
|
|
||||||
remainingAmount: budgetData.weekly_target
|
|
||||||
},
|
|
||||||
monthly: {
|
|
||||||
targetAmount: budgetData.monthly_target,
|
|
||||||
spentAmount: 0,
|
|
||||||
remainingAmount: budgetData.monthly_target
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
localStorage.setItem('budgetData', JSON.stringify(localBudgetData));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (categoryData && categoryData.length > 0) {
|
|
||||||
// 카테고리 예산 로컬 형식으로 변환
|
|
||||||
const localCategoryBudgets = categoryData.reduce((acc, curr) => {
|
|
||||||
acc[curr.category] = curr.amount;
|
|
||||||
return acc;
|
|
||||||
}, {} as Record<string, number>);
|
|
||||||
|
|
||||||
localStorage.setItem('categoryBudgets', JSON.stringify(localCategoryBudgets));
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('예산 데이터 다운로드 완료');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('예산 데이터 다운로드 실패:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 전체 데이터 동기화
|
|
||||||
export const syncAllData = async (userId: string): Promise<void> => {
|
export const syncAllData = async (userId: string): Promise<void> => {
|
||||||
if (!userId || !isSyncEnabled()) return;
|
if (!userId || !isSyncEnabled()) return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user