Remove on-premise Supabase test code

Remove code related to on-premise Supabase testing.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 22:35:44 +00:00
parent af52ec897f
commit 439653fa2f
25 changed files with 8 additions and 1080 deletions

View File

@@ -2,7 +2,7 @@
import React, { useState, useEffect } from 'react';
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { CloudUpload, RefreshCw, Database } from "lucide-react";
import { CloudUpload, RefreshCw } from "lucide-react";
import { isSyncEnabled, setSyncEnabled, syncAllData, getLastSyncTime } from "@/utils/syncUtils";
import { toast } from "@/hooks/useToast.wrapper";
import { useAuth } from "@/contexts/auth";
@@ -139,18 +139,6 @@ const SyncSettings = () => {
</div>
</div>
)}
{/* 온프레미스 Supabase 설정 버튼 추가 */}
<div className="pt-4 border-t border-gray-200">
<Button
variant="outline"
onClick={() => navigate('/supabase-settings')}
className="w-full flex items-center justify-center gap-2"
>
<Database className="h-4 w-4" />
<span> Supabase </span>
</Button>
</div>
</div>
);
};

View File

@@ -1,45 +0,0 @@
import React from "react";
import { RefreshCcw } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
interface ServerStatusAlertProps {
serverStatus: {
checked: boolean;
connected: boolean;
message: string;
};
checkServerConnection: () => Promise<void>;
}
const ServerStatusAlert: React.FC<ServerStatusAlertProps> = ({
serverStatus,
checkServerConnection,
}) => {
if (!serverStatus.checked || serverStatus.connected) {
return null;
}
return (
<Alert variant="destructive" className="mb-6">
<AlertTitle className="flex items-center">
<Button
variant="ghost"
size="sm"
className="ml-2 h-6 w-6 p-0"
onClick={checkServerConnection}
>
<RefreshCcw className="h-4 w-4" />
</Button>
</AlertTitle>
<AlertDescription>
{serverStatus.message}
<p className="mt-1 text-xs"> .</p>
</AlertDescription>
</Alert>
);
};
export default ServerStatusAlert;

View File

@@ -1,66 +0,0 @@
import React from "react";
import { Link } from "react-router-dom";
import { ArrowRight, Shield } from "lucide-react";
import { TestResults } from "@/lib/supabase/tests/types";
interface TestResultProps {
testResults: TestResults | null;
}
const SupabaseConnectionStatus: React.FC<TestResultProps> = ({ testResults }) => {
if (!testResults) {
return null;
}
return (
<details className="neuro-flat p-3 text-xs mb-4">
<summary className="cursor-pointer text-gray-500 font-medium"> </summary>
<div className="mt-2 space-y-2">
<div>
<p className="font-medium">Supabase URL:</p>
<p className="break-all bg-gray-100 p-1 rounded">{testResults?.url || '알 수 없음'}</p>
</div>
{testResults?.usingProxy && (
<div>
<p className="font-medium">CORS :</p>
<div className="flex items-center gap-1">
<Shield className="h-3 w-3 text-blue-500" />
<p className="break-all text-blue-500"> - {testResults.proxyUrl}</p>
</div>
</div>
)}
<div>
<p className="font-medium"> :</p>
<p>{testResults?.client ? '성공' : '실패'}</p>
</div>
<div>
<p className="font-medium"> :</p>
<p className="break-all">{navigator.userAgent}</p>
</div>
<div>
<p className="font-medium"> :</p>
<p>1.0.0</p>
</div>
{testResults && (
<div className="border-t pt-2 mt-2">
<p>REST API: {testResults.restApi ? '✅' : '❌'}</p>
<p>: {testResults.auth ? '✅' : '❌'}</p>
<p>: {testResults.database ? '✅' : '❌'}</p>
</div>
)}
<div className="text-right pt-1">
<Link
to="/supabase-settings"
className="inline-flex items-center text-neuro-income hover:underline"
>
<span>Supabase </span>
<ArrowRight className="h-3 w-3 ml-1" />
</Link>
</div>
</div>
</details>
);
};
export default SupabaseConnectionStatus;

View File

@@ -1,79 +0,0 @@
import React, { useState } from "react";
import { RefreshCw } from "lucide-react";
import { testSupabaseConnection } from "@/lib/supabase";
import { useToast } from "@/hooks/useToast.wrapper";
import { TestResults } from "@/lib/supabase/tests/types";
interface TestConnectionSectionProps {
setLoginError: (error: string | null) => void;
setTestResults: (results: TestResults) => void;
}
const TestConnectionSection: React.FC<TestConnectionSectionProps> = ({
setLoginError,
setTestResults
}) => {
const [testLoading, setTestLoading] = useState(false);
const { toast } = useToast();
const runConnectionTest = async () => {
setTestLoading(true);
setLoginError(null);
try {
const results = await testSupabaseConnection();
setTestResults(results);
if (results.errors.length === 0) {
toast({
title: "연결 테스트 성공",
description: "Supabase 서버 연결이 정상입니다.",
});
} else {
toast({
title: "연결 테스트 실패",
description: `오류 발생: ${results.errors[0]}`,
variant: "destructive"
});
}
} catch (error: any) {
console.error("연결 테스트 중 오류:", error);
setLoginError(error.message || "테스트 실행 중 예상치 못한 오류가 발생했습니다.");
toast({
title: "연결 테스트 오류",
description: "테스트 실행 중 예상치 못한 오류가 발생했습니다.",
variant: "destructive"
});
} finally {
setTestLoading(false);
}
};
return (
<div className="neuro-card p-4 mb-6">
<h3 className="text-sm font-medium mb-2">Supabase </h3>
<div className="flex justify-between items-center">
<button
onClick={runConnectionTest}
disabled={testLoading}
className="text-xs flex items-center text-neuro-income hover:underline"
>
{testLoading ? (
<>
<RefreshCw className="mr-1 h-3 w-3 animate-spin" />
...
</>
) : (
<>
<RefreshCw className="mr-1 h-3 w-3" />
</>
)}
</button>
</div>
</div>
);
};
export default TestConnectionSection;

View File

@@ -1,21 +0,0 @@
// 서버 연결 상태 타입
export interface ServerStatus {
checked: boolean;
connected: boolean;
message: string;
}
// 회원가입 응답 타입
export interface SignUpResponse {
error: any;
user: any;
redirectToSettings?: boolean;
emailConfirmationRequired?: boolean;
}
// 회원가입 폼 공통 props
export interface RegisterFormCommonProps {
serverStatus: ServerStatus;
setRegisterError: React.Dispatch<React.SetStateAction<string | null>>;
}

View File

@@ -1,34 +0,0 @@
import React from 'react';
import { Button } from "@/components/ui/button";
import { RefreshCw } from "lucide-react";
interface ConnectionTestButtonProps {
onClick: () => void;
isTesting: boolean;
}
const ConnectionTestButton: React.FC<ConnectionTestButtonProps> = ({ onClick, isTesting }) => {
return (
<Button
onClick={onClick}
disabled={isTesting}
variant="outline"
className="w-full mb-4"
>
{isTesting ? (
<>
<RefreshCw className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>
<RefreshCw className="mr-2 h-4 w-4" />
</>
)}
</Button>
);
};
export default ConnectionTestButton;

View File

@@ -1,39 +0,0 @@
import React from 'react';
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { Shield } from "lucide-react";
interface CorsProxyToggleProps {
useProxy: boolean;
setUseProxy: (use: boolean) => void;
}
const CorsProxyToggle: React.FC<CorsProxyToggleProps> = ({
useProxy,
setUseProxy
}) => {
return (
<div className="flex items-center justify-between space-x-2 py-2">
<div className="space-y-0.5">
<Label htmlFor="cors-proxy" className="cursor-pointer">
<div className="flex items-center">
<Shield className="h-4 w-4 mr-2 text-neuro-income" />
<span>CORS </span>
</div>
<p className="text-xs text-gray-500">
HTTP URL에
</p>
</Label>
</div>
<Switch
id="cors-proxy"
checked={useProxy}
onCheckedChange={setUseProxy}
className="data-[state=checked]:bg-neuro-income"
/>
</div>
);
};
export default CorsProxyToggle;

View File

@@ -1,20 +0,0 @@
import React from 'react';
import { TestResults } from '@/lib/supabase/tests/types';
interface ProxyInfoCardProps {
testResults: TestResults;
}
const ProxyInfoCard: React.FC<ProxyInfoCardProps> = ({ testResults }) => {
if (!testResults.usingProxy) return null;
return (
<div className="bg-blue-50 border border-blue-200 rounded p-2 mt-2">
<p className="text-xs">CORS : {testResults.proxyType || 'corsproxy.io'}</p>
<p className="text-xs break-all mt-1">{testResults.proxyUrl}</p>
</div>
);
};
export default ProxyInfoCard;

View File

@@ -1,37 +0,0 @@
import React from 'react';
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
interface ProxyTypeSelectorProps {
proxyType: string;
setProxyType: (type: string) => void;
}
const ProxyTypeSelector: React.FC<ProxyTypeSelectorProps> = ({
proxyType,
setProxyType
}) => {
return (
<div className="space-y-2">
<Label htmlFor="proxy-type" className="text-base"> </Label>
<Select value={proxyType} onValueChange={setProxyType}>
<SelectTrigger id="proxy-type" className="w-full">
<SelectValue placeholder="프록시 서비스 선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="cloudflare">Cloudflare Workers ()</SelectItem>
<SelectItem value="corsproxy.io">corsproxy.io</SelectItem>
<SelectItem value="thingproxy">thingproxy.freeboard.io</SelectItem>
<SelectItem value="allorigins">allorigins.win</SelectItem>
<SelectItem value="cors-anywhere">cors-anywhere.herokuapp.com</SelectItem>
</SelectContent>
</Select>
<p className="text-xs text-gray-500 mt-1">
Cloudflare .
</p>
</div>
);
};
export default ProxyTypeSelector;

View File

@@ -1,36 +0,0 @@
import React from 'react';
import { Button } from "@/components/ui/button";
import { Save, RefreshCw } from "lucide-react";
interface SaveSettingsButtonProps {
onClick: () => void;
isSaving: boolean;
}
const SaveSettingsButton: React.FC<SaveSettingsButtonProps> = ({
onClick,
isSaving
}) => {
return (
<Button
onClick={onClick}
disabled={isSaving}
className="w-full bg-neuro-income text-white"
>
{isSaving ? (
<>
<RefreshCw className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>
<Save className="mr-2 h-4 w-4" />
</>
)}
</Button>
);
};
export default SaveSettingsButton;

View File

@@ -1,85 +0,0 @@
import React, { useState } from 'react';
import { toast } from "@/hooks/useToast.wrapper";
import { testSupabaseConnection } from '@/lib/supabase';
import { TestResults } from '@/lib/supabase/tests/types';
// 분리된 컴포넌트들 임포트
import ConnectionTestButton from './ConnectionTestButton';
import TestResultItem from './TestResultItem';
import ProxyInfoCard from './ProxyInfoCard';
import ProxyRecommendationAlert from './ProxyRecommendationAlert';
import ErrorMessageCard from './ErrorMessageCard';
import TroubleshootingTips from './TroubleshootingTips';
import DebugInfoCollapsible from './DebugInfoCollapsible';
const SupabaseConnectionTest: React.FC = () => {
const [testResults, setTestResults] = useState<TestResults | null>(null);
const [isTesting, setIsTesting] = useState(false);
const [showDebug, setShowDebug] = useState(false);
const runConnectionTest = async () => {
setIsTesting(true);
try {
const results = await testSupabaseConnection();
setTestResults(results);
if (results.errors.length === 0 || (results.auth && results.restApi && results.database)) {
toast({
title: "연결 테스트 성공",
description: "Supabase 서버 연결이 정상입니다.",
});
} else {
toast({
title: "연결 테스트 실패",
description: `오류 발생: ${results.errors[0]}`,
variant: "destructive"
});
}
} catch (error: any) {
console.error("연결 테스트 중 오류:", error);
toast({
title: "연결 테스트 오류",
description: "테스트 실행 중 예상치 못한 오류가 발생했습니다.",
variant: "destructive"
});
} finally {
setIsTesting(false);
}
};
return (
<div>
<h2 className="text-lg font-semibold mb-4"> </h2>
<ConnectionTestButton
onClick={runConnectionTest}
isTesting={isTesting}
/>
{testResults && (
<div className="mt-4 space-y-3 text-sm">
<TestResultItem label="REST API" success={testResults.restApi} />
<TestResultItem label="인증" success={testResults.auth} />
<TestResultItem label="데이터베이스" success={testResults.database} />
<ProxyInfoCard testResults={testResults} />
<ProxyRecommendationAlert errors={testResults.errors} />
<ErrorMessageCard errors={testResults.errors} />
<TroubleshootingTips testResults={testResults} />
<DebugInfoCollapsible
testResults={testResults}
showDebug={showDebug}
setShowDebug={setShowDebug}
/>
</div>
)}
</div>
);
};
export default SupabaseConnectionTest;

View File

@@ -1,54 +0,0 @@
import React from 'react';
import { AlertCircle } from 'lucide-react';
const SupabaseHelpSection: React.FC = () => {
return (
<div>
<h2 className="text-lg font-semibold mb-2"></h2>
<p className="text-gray-500 text-sm mb-4">
Supabase :
</p>
<ul className="list-disc pl-5 text-sm text-gray-500 space-y-2">
<li>
<strong>Supabase URL</strong>: Supabase URL을 .
(: https://192.168.1.100:8000)
</li>
<li>
<strong>Anon Key</strong>: Supabase API anon/public .
</li>
<li>
<strong>CORS </strong>: HTTP URL에 .
HTTPS가 URL에 .
</li>
<li className="text-amber-500 font-medium">
HTTPS URL을 . HTTP URL을 CORS .
</li>
</ul>
{/* 오류 해결 팁 추가 */}
<div className="mt-6 border-t pt-4">
<h3 className="flex items-center text-sm font-semibold mb-2">
<AlertCircle className="h-4 w-4 mr-1 text-amber-500" />
<span> </span>
</h3>
<ul className="list-disc pl-5 text-xs text-gray-500 space-y-2">
<li>
<strong>REST API </strong>: CORS . Supabase CORS .
</li>
<li>
<strong> , API </strong>: CORS . CORS .
</li>
<li>
<strong> </strong>: Supabase , .
</li>
<li>
<strong>HTTPS </strong>: HTTP , HTTPS Supabase URL이 .
</li>
</ul>
</div>
</div>
);
};
export default SupabaseHelpSection;

View File

@@ -1,40 +0,0 @@
import React from 'react';
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
interface SupabaseKeyInputProps {
supabaseKey: string;
setSupabaseKey: (key: string) => void;
}
const SupabaseKeyInput: React.FC<SupabaseKeyInputProps> = ({
supabaseKey,
setSupabaseKey
}) => {
return (
<div className="space-y-2">
<Label htmlFor="supabase-key" className="text-base">Supabase Anon Key</Label>
<div className="relative">
<svg
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" />
</svg>
<Input
id="supabase-key"
placeholder="your-anon-key"
value={supabaseKey}
onChange={(e) => setSupabaseKey(e.target.value)}
className="pl-10 neuro-pressed"
/>
</div>
</div>
);
};
export default SupabaseKeyInput;

View File

@@ -1,137 +0,0 @@
import React, { useState, useEffect } from 'react';
import { toast } from "@/hooks/useToast.wrapper";
import {
configureSupabase,
isCorsProxyEnabled,
getProxyType
} from "@/lib/supabase/config";
// 분리된 컴포넌트들 임포트
import SupabaseUrlInput from './SupabaseUrlInput';
import SupabaseKeyInput from './SupabaseKeyInput';
import CorsProxyToggle from './CorsProxyToggle';
import ProxyTypeSelector from './ProxyTypeSelector';
import SaveSettingsButton from './SaveSettingsButton';
interface SupabaseSettingsFormProps {
onSaved: () => void;
}
const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved }) => {
// 상태 관리
const [formState, setFormState] = useState({
supabaseUrl: '',
supabaseKey: '',
useProxy: true, // 기본값을 true로 변경
proxyType: 'cloudflare', // 기본값을 cloudflare로 변경
isSaving: false
});
// 상태 업데이트 핸들러
const updateState = (update: Partial<typeof formState>) => {
setFormState(prev => ({ ...prev, ...update }));
};
// 저장된 설정 불러오기
useEffect(() => {
const savedUrl = localStorage.getItem('supabase_url');
const savedKey = localStorage.getItem('supabase_key');
const proxyEnabled = localStorage.getItem('use_cors_proxy') === 'true';
const savedProxyType = getProxyType();
setFormState(prev => ({
...prev,
supabaseUrl: savedUrl || '',
supabaseKey: savedKey || '',
useProxy: proxyEnabled === false ? false : true, // 저장된 값이 명시적으로 false인 경우에만 false, 아니면 기본값 true
proxyType: savedProxyType || 'cloudflare'
}));
}, []);
// URL 유효성 검사
const validateUrl = (url: string): boolean => {
return /^https?:\/\/.+/.test(url);
};
// 폼 제출 및 설정 저장
const handleSave = () => {
const { supabaseUrl, supabaseKey, useProxy, proxyType } = formState;
// 입력값 검증
if (!supabaseUrl || !supabaseKey) {
toast({
title: "입력 오류",
description: "Supabase URL과 Anon Key를 모두 입력해주세요.",
variant: "destructive"
});
return;
}
if (!validateUrl(supabaseUrl)) {
toast({
title: "URL 오류",
description: "유효한 URL 형식이 아닙니다. http:// 또는 https://로 시작하는 URL을 입력해주세요.",
variant: "destructive"
});
return;
}
// 저장 처리
updateState({ isSaving: true });
try {
// Supabase 설정 적용
configureSupabase(supabaseUrl, supabaseKey, useProxy, proxyType);
toast({
title: "설정 저장 완료",
description: "Supabase 설정이 저장되었습니다. 변경사항을 적용합니다.",
});
onSaved();
} catch (error) {
console.error('Supabase 설정 저장 오류:', error);
toast({
title: "설정 저장 실패",
description: "Supabase 설정을 저장하는 중 오류가 발생했습니다.",
variant: "destructive"
});
updateState({ isSaving: false });
}
};
return (
<div className="space-y-6">
<SupabaseUrlInput
supabaseUrl={formState.supabaseUrl}
setSupabaseUrl={(url) => updateState({ supabaseUrl: url })}
useProxy={formState.useProxy}
/>
<SupabaseKeyInput
supabaseKey={formState.supabaseKey}
setSupabaseKey={(key) => updateState({ supabaseKey: key })}
/>
<CorsProxyToggle
useProxy={formState.useProxy}
setUseProxy={(value) => updateState({ useProxy: value })}
/>
{formState.useProxy && (
<ProxyTypeSelector
proxyType={formState.proxyType}
setProxyType={(type) => updateState({ proxyType: type })}
/>
)}
<SaveSettingsButton
onClick={handleSave}
isSaving={formState.isSaving}
/>
</div>
);
};
export default SupabaseSettingsForm;

View File

@@ -1,53 +0,0 @@
import React from 'react';
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { DatabaseIcon, AlertTriangle, Check } from "lucide-react";
interface SupabaseUrlInputProps {
supabaseUrl: string;
setSupabaseUrl: (url: string) => void;
useProxy: boolean;
}
const SupabaseUrlInput: React.FC<SupabaseUrlInputProps> = ({
supabaseUrl,
setSupabaseUrl,
useProxy
}) => {
const isHttpsUrl = supabaseUrl.startsWith("https://");
const suggestProxy = supabaseUrl.startsWith("http://") && !useProxy;
return (
<div className="space-y-2">
<Label htmlFor="supabase-url" className="text-base">Supabase URL</Label>
<div className="relative">
<DatabaseIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 h-5 w-5" />
<Input
id="supabase-url"
placeholder="http://your-supabase-url.com"
value={supabaseUrl}
onChange={(e) => setSupabaseUrl(e.target.value)}
className="pl-10 neuro-pressed"
/>
</div>
{/* URL 관련 경고 및 안내 추가 */}
{suggestProxy && (
<div className="flex items-center text-amber-500 text-xs mt-1 p-2 bg-amber-50 rounded-md">
<AlertTriangle className="h-4 w-4 mr-1 flex-shrink-0" />
<span>HTTP URL을 . CORS .</span>
</div>
)}
{isHttpsUrl && (
<div className="flex items-center text-green-500 text-xs mt-1 p-2 bg-green-50 rounded-md">
<Check className="h-4 w-4 mr-1 flex-shrink-0" />
<span>HTTPS URL을 . .</span>
</div>
)}
</div>
);
};
export default SupabaseUrlInput;

View File

@@ -1,20 +0,0 @@
import React from 'react';
interface TestResultItemProps {
label: string;
success: boolean;
}
const TestResultItem: React.FC<TestResultItemProps> = ({ label, success }) => {
return (
<div className="flex justify-between">
<span className="font-medium">{label}:</span>
<span className={success ? 'text-green-500' : 'text-red-500'}>
{success ? '✅ 성공' : '❌ 실패'}
</span>
</div>
);
};
export default TestResultItem;