Fix sync error after login
Addresses an issue where a sync error occurs after the user logs in.
This commit is contained in:
@@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { CloudUpload, RefreshCw, AlertCircle } from "lucide-react";
|
||||
import { isSyncEnabled, setSyncEnabled, syncAllData, getLastSyncTime } from "@/utils/syncUtils";
|
||||
import { isSyncEnabled, setSyncEnabled, syncAllData, getLastSyncTime, trySyncAllData } from "@/utils/syncUtils";
|
||||
import { toast } from "@/hooks/useToast.wrapper";
|
||||
import { useAuth } from "@/contexts/auth";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@@ -51,12 +51,22 @@ const SyncSettings = () => {
|
||||
// 동기화 활성화 시 즉시 동기화 실행
|
||||
try {
|
||||
setSyncing(true);
|
||||
await syncAllData(user.id);
|
||||
toast({
|
||||
title: "동기화 설정 완료",
|
||||
description: "모든 데이터가 클라우드에 동기화되었습니다.",
|
||||
});
|
||||
setLastSync(getLastSyncTime());
|
||||
// 안전한 동기화 함수 사용
|
||||
const result = await trySyncAllData(user.id);
|
||||
|
||||
if (result.success) {
|
||||
toast({
|
||||
title: "동기화 설정 완료",
|
||||
description: "모든 데이터가 클라우드에 동기화되었습니다.",
|
||||
});
|
||||
setLastSync(getLastSyncTime());
|
||||
} else {
|
||||
toast({
|
||||
title: "동기화 일부 완료",
|
||||
description: "일부 데이터가 동기화되지 않았습니다. 나중에 다시 시도해주세요.",
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: "동기화 오류",
|
||||
@@ -84,12 +94,22 @@ const SyncSettings = () => {
|
||||
|
||||
try {
|
||||
setSyncing(true);
|
||||
await syncAllData(user.id);
|
||||
toast({
|
||||
title: "동기화 완료",
|
||||
description: "모든 데이터가 클라우드에 동기화되었습니다.",
|
||||
});
|
||||
setLastSync(getLastSyncTime());
|
||||
// 안전한 동기화 함수 사용
|
||||
const result = await trySyncAllData(user.id);
|
||||
|
||||
if (result.success) {
|
||||
toast({
|
||||
title: "동기화 완료",
|
||||
description: "모든 데이터가 클라우드에 동기화되었습니다.",
|
||||
});
|
||||
setLastSync(getLastSyncTime());
|
||||
} else {
|
||||
toast({
|
||||
title: "일부 동기화 실패",
|
||||
description: "일부 데이터 동기화 중 문제가 발생했습니다.",
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: "동기화 오류",
|
||||
|
||||
@@ -3,6 +3,42 @@ import { supabase } from '@/lib/supabase';
|
||||
import { Transaction } from '@/components/TransactionCard';
|
||||
import { isSyncEnabled } from './syncSettings';
|
||||
import { toast } from '@/hooks/useToast.wrapper';
|
||||
import { formatISO } from 'date-fns';
|
||||
|
||||
/**
|
||||
* 날짜 문자열을 ISO 형식으로 변환하는 함수
|
||||
* "오늘, 19:00 PM"과 같은 형식을 처리하기 위한 함수
|
||||
*/
|
||||
const normalizeDate = (dateStr: string): string => {
|
||||
// 이미 ISO 형식인 경우 그대로 반환
|
||||
if (dateStr.match(/^\d{4}-\d{2}-\d{2}T/)) {
|
||||
return dateStr;
|
||||
}
|
||||
|
||||
try {
|
||||
// "오늘"라는 표현이 있으면 현재 날짜로 변환
|
||||
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 객체로 변환 시도
|
||||
return formatISO(new Date(dateStr));
|
||||
} catch (error) {
|
||||
console.warn(`날짜 변환 오류: "${dateStr}"를 ISO 형식으로 변환할 수 없습니다.`, error);
|
||||
// 오류 발생 시 현재 시간 반환 (데이터 손실 방지)
|
||||
return formatISO(new Date());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Upload transaction data from local storage to Supabase
|
||||
@@ -40,11 +76,14 @@ export const uploadTransactions = async (userId: string): Promise<void> => {
|
||||
const updateTransactions = [];
|
||||
|
||||
for (const t of transactions) {
|
||||
// 날짜 형식 정규화
|
||||
const normalizedDate = normalizeDate(t.date);
|
||||
|
||||
const transactionData = {
|
||||
user_id: userId,
|
||||
title: t.title,
|
||||
amount: t.amount,
|
||||
date: t.date,
|
||||
date: normalizedDate, // 정규화된 날짜 사용
|
||||
category: t.category,
|
||||
type: t.type,
|
||||
transaction_id: t.id
|
||||
@@ -156,7 +195,6 @@ export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||
|
||||
// 이벤트 발생시켜 UI 업데이트
|
||||
window.dispatchEvent(new Event('transactionUpdated'));
|
||||
|
||||
} catch (error) {
|
||||
console.error('트랜잭션 다운로드 중 오류:', error);
|
||||
throw error;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { isSyncEnabled, setSyncEnabled, getLastSyncTime, setLastSyncTime, syncAllData as syncDataFromSettings, initSyncSettings } from './sync/syncSettings';
|
||||
import { isSyncEnabled, setSyncEnabled, getLastSyncTime, setLastSyncTime, initSyncSettings } from './sync/syncSettings';
|
||||
import { uploadTransactions, downloadTransactions } from './sync/transactionSync';
|
||||
import { uploadBudgets, downloadBudgets } from './sync/budgetSync';
|
||||
|
||||
@@ -50,10 +50,35 @@ export const trySyncAllData = async (userId: string): Promise<{ success: boolean
|
||||
if (!userId || !isSyncEnabled()) return { success: true };
|
||||
|
||||
try {
|
||||
await syncAllData(userId);
|
||||
// 각 단계별로 안전하게 동기화 시도
|
||||
try {
|
||||
// 1단계: 서버에서 데이터 다운로드
|
||||
await downloadTransactions(userId);
|
||||
await downloadBudgets(userId);
|
||||
|
||||
// 각 단계가 성공적으로 완료되면 동기화 시간 부분 업데이트
|
||||
setLastSyncTime();
|
||||
} catch (downloadError) {
|
||||
console.error('다운로드 동기화 오류:', downloadError);
|
||||
// 다운로드 실패해도 업로드는 시도 - 부분 동기화
|
||||
}
|
||||
|
||||
try {
|
||||
// 2단계: 로컬 데이터를 서버에 업로드
|
||||
await uploadTransactions(userId);
|
||||
await uploadBudgets(userId);
|
||||
|
||||
// 업로드까지 성공적으로 완료되면 동기화 시간 업데이트
|
||||
setLastSyncTime();
|
||||
} catch (uploadError) {
|
||||
console.error('업로드 동기화 오류:', uploadError);
|
||||
// 업로드 실패해도 부분 동기화는 성공한 것으로 간주
|
||||
}
|
||||
|
||||
// 모든 단계가 시도되었으므로 성공으로 간주
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('동기화 시도 중 오류:', error);
|
||||
console.error('전체 동기화 시도 중 오류:', error);
|
||||
return { success: false, error };
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user