Format dates for synchronization

Use ISO format for data synchronization and user-friendly format for display.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-17 23:47:05 +00:00
parent ce12e99f6d
commit 71aebf8b5b
5 changed files with 82 additions and 4 deletions

View File

@@ -3,6 +3,45 @@ import { Transaction } from '@/components/TransactionCard';
import { supabase } from '@/lib/supabase';
import { isSyncEnabled } from '@/utils/syncUtils';
import { useAuth } from '@/contexts/auth/AuthProvider';
import { formatISO, parseISO } from 'date-fns';
// ISO 형식으로 날짜 변환 (Supabase 저장용)
const convertDateToISO = (dateStr: string): string => {
try {
// 이미 ISO 형식인 경우 그대로 반환
if (dateStr.match(/^\d{4}-\d{2}-\d{2}T/)) {
return dateStr;
}
// "오늘, 시간" 형식 처리
if (dateStr.includes('오늘')) {
const today = new Date();
// 시간 추출 시도
const timeMatch = dateStr.match(/(\d{1,2}):(\d{2})/);
if (timeMatch) {
const hours = parseInt(timeMatch[1], 10);
const minutes = parseInt(timeMatch[2], 10);
today.setHours(hours, minutes, 0, 0);
}
return formatISO(today);
}
// 일반 날짜 문자열은 그대로 Date 객체로 변환 시도
const date = new Date(dateStr);
if (!isNaN(date.getTime())) {
return formatISO(date);
}
// 변환 실패 시 현재 시간 반환
console.warn(`날짜 변환 오류: "${dateStr}"를 ISO 형식으로 변환할 수 없습니다.`);
return formatISO(new Date());
} catch (error) {
console.error(`날짜 변환 오류: "${dateStr}"`, error);
return formatISO(new Date());
}
};
// Supabase와 트랜잭션 동기화
export const syncTransactionsWithSupabase = async (user: any, transactions: Transaction[]): Promise<Transaction[]> => {
@@ -56,12 +95,15 @@ export const updateTransactionInSupabase = async (user: any, transaction: Transa
if (!user || !isSyncEnabled()) return;
try {
// 날짜를 ISO 형식으로 변환
const isoDate = convertDateToISO(transaction.date);
const { error } = await supabase.from('transactions')
.upsert({
user_id: user.id,
title: transaction.title,
amount: transaction.amount,
date: transaction.date,
date: isoDate, // ISO 형식 사용
category: transaction.category,
type: transaction.type,
transaction_id: transaction.id
@@ -69,6 +111,8 @@ export const updateTransactionInSupabase = async (user: any, transaction: Transa
if (error) {
console.error('트랜잭션 업데이트 오류:', error);
} else {
console.log('Supabase 트랜잭션 업데이트 성공:', transaction.id);
}
} catch (error) {
console.error('Supabase 업데이트 오류:', error);
@@ -86,6 +130,8 @@ export const deleteTransactionFromSupabase = async (user: any, transactionId: st
if (error) {
console.error('트랜잭션 삭제 오류:', error);
} else {
console.log('Supabase 트랜잭션 삭제 성공:', transactionId);
}
} catch (error) {
console.error('Supabase 삭제 오류:', error);

View File

@@ -4,6 +4,7 @@ import { Transaction } from '@/components/TransactionCard';
import { saveTransactionsToStorage } from '../../storageUtils';
import { deleteTransactionFromSupabase } from '../../supabaseUtils';
import { toast } from '@/hooks/useToast.wrapper';
import { normalizeDate } from '@/utils/sync/transaction/dateUtils';
/**
* 스토리지 및 Supabase 삭제 처리
@@ -31,6 +32,10 @@ export const handleDeleteStorage = (
// 동기적 에러를 피하기 위해 setTimeout으로 감싸기
setTimeout(() => {
try {
// ISO 형식으로 날짜 변환
const isoDate = normalizeDate(transactionToDelete.date);
console.log('삭제 중인 트랜잭션 ISO 날짜:', isoDate);
deleteTransactionFromSupabase(user, id)
.catch(error => {
console.error('Supabase 삭제 오류:', error);

View File

@@ -6,6 +6,7 @@ import { toast } from '@/hooks/useToast.wrapper';
import { saveTransactionsToStorage } from '../storageUtils';
import { updateTransactionInSupabase } from '../supabaseUtils';
import { TransactionOperationProps } from './types';
import { normalizeDate } from '@/utils/sync/transaction/dateUtils';
/**
* 트랜잭션 업데이트 기능
@@ -28,9 +29,15 @@ export const useUpdateTransaction = (
// 상태 업데이트
setTransactions(updatedTransactions);
// Supabase 업데이트 시도
// Supabase 업데이트 시도 (날짜 형식 변환 추가)
if (user) {
updateTransactionInSupabase(user, updatedTransaction);
// ISO 형식으로 날짜 변환
const transactionWithIsoDate = {
...updatedTransaction,
dateForSync: normalizeDate(updatedTransaction.date)
};
updateTransactionInSupabase(user, transactionWithIsoDate);
}
// 이벤트 발생

View File

@@ -43,6 +43,20 @@ export const useTransactionsEvents = (
}, 200);
};
// 트랜잭션 변경 이벤트 (통합 이벤트)
const handleTransactionChange = (e: CustomEvent) => {
console.log('트랜잭션 변경 이벤트 감지:', e.detail?.type);
// 처리 중 중복 호출 방지
if (isProcessing) return;
isProcessing = true;
setTimeout(() => {
loadTransactions();
isProcessing = false;
}, 150);
};
// 스토리지 이벤트
const handleStorageEvent = (e: StorageEvent) => {
if (e.key === 'transactions' || e.key === null) {
@@ -76,6 +90,7 @@ export const useTransactionsEvents = (
// 이벤트 리스너 등록
window.addEventListener('transactionUpdated', handleTransactionUpdate);
window.addEventListener('transactionDeleted', handleTransactionDelete);
window.addEventListener('transactionChanged', handleTransactionChange as EventListener);
window.addEventListener('storage', handleStorageEvent);
window.addEventListener('focus', handleFocus);
@@ -89,6 +104,7 @@ export const useTransactionsEvents = (
console.log('useTransactions - 이벤트 리스너 제거');
window.removeEventListener('transactionUpdated', handleTransactionUpdate);
window.removeEventListener('transactionDeleted', handleTransactionDelete);
window.removeEventListener('transactionChanged', handleTransactionChange as EventListener);
window.removeEventListener('storage', handleStorageEvent);
window.removeEventListener('focus', handleFocus);
};