Remove offline mode option
This commit removes the offline mode functionality and focuses on resolving server-side issues.
This commit is contained in:
@@ -9,9 +9,15 @@ export const showAuthToast = (title: string, description: string, variant: 'defa
|
|||||||
|
|
||||||
// 에러 메시지 처리 유틸리티 함수
|
// 에러 메시지 처리 유틸리티 함수
|
||||||
export const handleNetworkError = (error: any): string => {
|
export const handleNetworkError = (error: any): string => {
|
||||||
return error.message && error.message.includes('fetch')
|
if (error.message && error.message.includes('fetch')) {
|
||||||
? '서버 연결에 실패했습니다. 네트워크 연결을 확인해주세요.'
|
return '서버 연결에 실패했습니다. 네트워크 연결을 확인해주세요.';
|
||||||
: (error.message || '예상치 못한 오류가 발생했습니다.');
|
} else if (error.message && error.message.includes('CORS')) {
|
||||||
|
return 'CORS 오류가 발생했습니다. 서버 설정 또는 CORS 프록시를 확인하세요.';
|
||||||
|
} else if (error.message && error.message.includes('NetworkError')) {
|
||||||
|
return '네트워크 오류가 발생했습니다. 인터넷 연결을 확인하세요.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.message || '예상치 못한 오류가 발생했습니다.';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 응답 파싱 유틸리티 함수
|
// 응답 파싱 유틸리티 함수
|
||||||
@@ -60,23 +66,98 @@ export const hasCorsIssue = (error: any): boolean => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 오프라인 모드 확인
|
// Supabase 연결 상태 확인
|
||||||
export const isOfflineMode = (): boolean => {
|
export const checkSupabaseConnection = async (): Promise<boolean> => {
|
||||||
return !navigator.onLine || localStorage.getItem('offline_mode') === 'true';
|
try {
|
||||||
|
const { data, error } = await supabase.auth.getSession();
|
||||||
|
|
||||||
|
// 오류가 없으면 연결 성공
|
||||||
|
if (!error) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 오류 메시지 확인
|
||||||
|
if (error.message && (
|
||||||
|
error.message.includes('Failed to fetch') ||
|
||||||
|
error.message.includes('Network') ||
|
||||||
|
error.message.includes('CORS')
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 다른 오류는 연결은 됐지만 세션/인증 관련 오류이므로 연결은 성공
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Supabase 연결 확인 중 오류:', err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 데모 모드 사용자 생성 (오프라인 환경용)
|
// 서버 연결 상태 검사
|
||||||
export const createDemoUser = (email: string, username: string) => {
|
export const verifyServerConnection = async (): Promise<{
|
||||||
// 데모용 가상 사용자 정보
|
connected: boolean;
|
||||||
const demoUser = {
|
message: string;
|
||||||
id: 'demo-' + Date.now(),
|
}> => {
|
||||||
email,
|
try {
|
||||||
user_metadata: { username },
|
const start = Date.now();
|
||||||
created_at: new Date().toISOString()
|
|
||||||
};
|
// Supabase URL 가져오기
|
||||||
|
const supabaseUrl = localStorage.getItem('supabase_url') || 'http://a11.ism.kr:8000';
|
||||||
// 로컬 스토리지에 저장
|
|
||||||
localStorage.setItem('demo_user', JSON.stringify(demoUser));
|
// 단순 헬스 체크 요청
|
||||||
|
const response = await fetch(`${supabaseUrl}/rest/v1/`, {
|
||||||
return demoUser;
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const elapsed = Date.now() - start;
|
||||||
|
|
||||||
|
if (response.ok || response.status === 401) {
|
||||||
|
// 401도 서버가 응답했다는 의미이므로 연결 성공으로 간주
|
||||||
|
return {
|
||||||
|
connected: true,
|
||||||
|
message: `서버 연결 성공 (응답 시간: ${elapsed}ms)`
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
connected: false,
|
||||||
|
message: `서버 응답 오류: ${response.status} ${response.statusText}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('서버 연결 확인 중 오류:', error);
|
||||||
|
|
||||||
|
// 오류 유형에 따른 메시지 설정
|
||||||
|
let errorMessage = '알 수 없는 네트워크 오류';
|
||||||
|
|
||||||
|
if (error.message) {
|
||||||
|
if (error.message.includes('Failed to fetch')) {
|
||||||
|
errorMessage = 'CORS 정책 오류 또는 서버 연결 실패';
|
||||||
|
} else if (error.message.includes('NetworkError')) {
|
||||||
|
errorMessage = '네트워크 연결 실패';
|
||||||
|
} else if (error.message.includes('TypeError')) {
|
||||||
|
errorMessage = '네트워크 요청 형식 오류';
|
||||||
|
} else {
|
||||||
|
errorMessage = error.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
connected: false,
|
||||||
|
message: errorMessage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 서버 URL 검증
|
||||||
|
export const validateServerUrl = (url: string): boolean => {
|
||||||
|
try {
|
||||||
|
// URL 유효성 검사
|
||||||
|
new URL(url);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
|
|
||||||
import { supabase } from '@/lib/supabase';
|
import { supabase } from '@/lib/supabase';
|
||||||
import { handleNetworkError, parseResponse, showAuthToast, isOfflineMode, createDemoUser } from './auth.utils';
|
import { handleNetworkError, parseResponse, showAuthToast, verifyServerConnection } from './auth.utils';
|
||||||
|
|
||||||
export const signIn = async (email: string, password: string) => {
|
export const signIn = async (email: string, password: string) => {
|
||||||
try {
|
try {
|
||||||
// 오프라인 모드 확인
|
// 서버 연결 상태 먼저 확인
|
||||||
if (isOfflineMode()) {
|
const connectionStatus = await verifyServerConnection();
|
||||||
console.log('오프라인 모드로 로그인 시도:', email);
|
if (!connectionStatus.connected) {
|
||||||
|
showAuthToast('서버 연결 실패', connectionStatus.message, 'destructive');
|
||||||
// 데모 사용자 생성 (데모 모드용)
|
return {
|
||||||
const demoUser = createDemoUser(email, email.split('@')[0]);
|
error: { message: `서버 연결에 실패했습니다: ${connectionStatus.message}` },
|
||||||
|
user: null
|
||||||
showAuthToast('로그인 성공', '오프라인 모드로 로그인되었습니다.');
|
};
|
||||||
return { error: null, user: demoUser };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('로그인 시도 중:', email);
|
console.log('로그인 시도 중:', email);
|
||||||
|
|||||||
@@ -1,23 +1,12 @@
|
|||||||
|
|
||||||
import { supabase } from '@/lib/supabase';
|
import { supabase } from '@/lib/supabase';
|
||||||
import { handleNetworkError, showAuthToast, isOfflineMode, createDemoUser } from './auth.utils';
|
import { handleNetworkError, showAuthToast } from './auth.utils';
|
||||||
|
|
||||||
export const signUp = async (email: string, password: string, username: string) => {
|
export const signUp = async (email: string, password: string, username: string) => {
|
||||||
try {
|
try {
|
||||||
// 오프라인 모드 확인
|
|
||||||
if (isOfflineMode()) {
|
|
||||||
console.log('오프라인 모드로 회원가입 시도:', { email, username });
|
|
||||||
|
|
||||||
// 데모 사용자 생성
|
|
||||||
const demoUser = createDemoUser(email, username);
|
|
||||||
|
|
||||||
showAuthToast('회원가입 성공', '오프라인 모드로 회원가입되었습니다.');
|
|
||||||
return { error: null, user: demoUser };
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('회원가입 시도:', { email, username });
|
console.log('회원가입 시도:', { email, username });
|
||||||
|
|
||||||
// 기본 회원가입 시도
|
// 회원가입 시도
|
||||||
const { data, error } = await supabase.auth.signUp({
|
const { data, error } = await supabase.auth.signUp({
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
@@ -44,14 +33,17 @@ export const signUp = async (email: string, password: string, username: string)
|
|||||||
errorMessage = '서버 연결 문제: 이메일 검증에 실패했습니다.';
|
errorMessage = '서버 연결 문제: 이메일 검증에 실패했습니다.';
|
||||||
} else if (error.message.includes('json')) {
|
} else if (error.message.includes('json')) {
|
||||||
errorMessage = '서버 응답 처리 오류: 네트워크 연결을 확인하세요.';
|
errorMessage = '서버 응답 처리 오류: 네트워크 연결을 확인하세요.';
|
||||||
|
} else if (error.message.includes('fetch failed')) {
|
||||||
|
errorMessage = '서버 연결에 실패했습니다. 네트워크 연결 또는 서버 상태를 확인하세요.';
|
||||||
|
} else if (error.message.includes('Failed to fetch')) {
|
||||||
|
errorMessage = 'CORS 오류가 발생했습니다. 서버 설정을 확인하거나 네트워크 관리자에게 문의하세요.';
|
||||||
}
|
}
|
||||||
|
|
||||||
showAuthToast('회원가입 실패', errorMessage, 'destructive');
|
showAuthToast('회원가입 실패', errorMessage, 'destructive');
|
||||||
return { error, user: null };
|
return { error, user: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 즉시 로그인이 필요한 경우 여기서 처리
|
// 성공 메시지 표시
|
||||||
// 기본적으로는 이메일 확인 요청
|
|
||||||
showAuthToast('회원가입 성공', '이메일 확인 후 로그인해주세요.');
|
showAuthToast('회원가입 성공', '이메일 확인 후 로그인해주세요.');
|
||||||
|
|
||||||
// 개발 환경 또는 데모 모드에서는 즉시 로그인 허용
|
// 개발 환경 또는 데모 모드에서는 즉시 로그인 허용
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@@ -6,6 +7,8 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { ArrowRight, Mail, KeyRound, User, Eye, EyeOff } from "lucide-react";
|
import { ArrowRight, Mail, KeyRound, User, Eye, EyeOff } from "lucide-react";
|
||||||
import { useToast } from "@/hooks/useToast.wrapper";
|
import { useToast } from "@/hooks/useToast.wrapper";
|
||||||
import { useAuth } from "@/contexts/auth";
|
import { useAuth } from "@/contexts/auth";
|
||||||
|
import TestConnectionSection from "@/components/auth/TestConnectionSection";
|
||||||
|
import SupabaseConnectionStatus from "@/components/auth/SupabaseConnectionStatus";
|
||||||
|
|
||||||
const Register = () => {
|
const Register = () => {
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
@@ -14,6 +17,8 @@ const Register = () => {
|
|||||||
const [confirmPassword, setConfirmPassword] = useState("");
|
const [confirmPassword, setConfirmPassword] = useState("");
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [registerError, setRegisterError] = useState<string | null>(null);
|
||||||
|
const [testResults, setTestResults] = useState<any>(null);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { signUp, user } = useAuth();
|
const { signUp, user } = useAuth();
|
||||||
@@ -27,6 +32,7 @@ const Register = () => {
|
|||||||
|
|
||||||
const handleRegister = async (e: React.FormEvent) => {
|
const handleRegister = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
setRegisterError(null);
|
||||||
|
|
||||||
if (!username || !email || !password || !confirmPassword) {
|
if (!username || !email || !password || !confirmPassword) {
|
||||||
toast({
|
toast({
|
||||||
@@ -51,12 +57,15 @@ const Register = () => {
|
|||||||
try {
|
try {
|
||||||
const { error, user } = await signUp(email, password, username);
|
const { error, user } = await signUp(email, password, username);
|
||||||
|
|
||||||
if (!error && user) {
|
if (error) {
|
||||||
// 데모 모드에서는 즉시 메인 페이지로 이동
|
setRegisterError(error.message || '알 수 없는 오류가 발생했습니다.');
|
||||||
navigate("/");
|
} else if (user) {
|
||||||
|
// 회원가입 성공 시 로그인 페이지로 이동
|
||||||
|
navigate("/login");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error("회원가입 처리 중 예외 발생:", error);
|
console.error("회원가입 처리 중 예외 발생:", error);
|
||||||
|
setRegisterError(error.message || '예상치 못한 오류가 발생했습니다.');
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@@ -140,6 +149,12 @@ const Register = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{registerError && (
|
||||||
|
<div className="p-3 bg-red-50 border border-red-200 rounded-md text-red-700 text-sm">
|
||||||
|
<p>{registerError}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-full bg-neuro-income hover:bg-neuro-income/80 text-white py-6 h-auto"
|
className="w-full bg-neuro-income hover:bg-neuro-income/80 text-white py-6 h-auto"
|
||||||
@@ -151,7 +166,7 @@ const Register = () => {
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center">
|
<div className="text-center mb-4">
|
||||||
<p className="text-gray-500">
|
<p className="text-gray-500">
|
||||||
이미 계정이 있으신가요?{" "}
|
이미 계정이 있으신가요?{" "}
|
||||||
<Link to="/login" className="text-neuro-income font-medium hover:underline">
|
<Link to="/login" className="text-neuro-income font-medium hover:underline">
|
||||||
@@ -159,6 +174,14 @@ const Register = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Supabase 연결 테스트 섹션 */}
|
||||||
|
<TestConnectionSection
|
||||||
|
setLoginError={setRegisterError}
|
||||||
|
setTestResults={setTestResults}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SupabaseConnectionStatus testResults={testResults} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user