홍길동
-honggildong@example.com
-데이터 동기화
-계정
-앱 설정
-앱 버전 0.1
-diff --git a/package-lock.json b/package-lock.json
index da48d6b..b672b68 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,6 +42,7 @@
"@radix-ui/react-tooltip": "^1.1.4",
"@supabase/supabase-js": "^2.49.1",
"@tanstack/react-query": "^5.56.2",
+ "@types/react-helmet": "^6.1.11",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
@@ -53,6 +54,7 @@
"react": "^18.3.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
+ "react-helmet": "^6.1.0",
"react-hook-form": "^7.53.0",
"react-resizable-panels": "^2.1.3",
"react-router-dom": "^6.26.2",
@@ -3293,14 +3295,12 @@
"version": "15.7.13",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.12",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
"integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -3317,6 +3317,15 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-helmet": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
+ "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/slice-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/slice-ansi/-/slice-ansi-4.0.0.tgz",
@@ -6836,6 +6845,27 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-fast-compare": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
+ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
+ "license": "MIT"
+ },
+ "node_modules/react-helmet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
+ "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-fast-compare": "^3.1.1",
+ "react-side-effect": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0"
+ }
+ },
"node_modules/react-hook-form": {
"version": "7.53.1",
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.1.tgz",
@@ -6947,6 +6977,15 @@
"react-dom": ">=16.8"
}
},
+ "node_modules/react-side-effect": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
+ "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.3.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-smooth": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz",
diff --git a/package.json b/package.json
index 13e2ce5..93e8717 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"@radix-ui/react-tooltip": "^1.1.4",
"@supabase/supabase-js": "^2.49.1",
"@tanstack/react-query": "^5.56.2",
+ "@types/react-helmet": "^6.1.11",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
@@ -56,6 +57,7 @@
"react": "^18.3.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
+ "react-helmet": "^6.1.0",
"react-hook-form": "^7.53.0",
"react-resizable-panels": "^2.1.3",
"react-router-dom": "^6.26.2",
diff --git a/src/components/SupabaseTestPanel.tsx b/src/components/SupabaseTestPanel.tsx
new file mode 100644
index 0000000..e680612
--- /dev/null
+++ b/src/components/SupabaseTestPanel.tsx
@@ -0,0 +1,151 @@
+
+import React, { useState } from 'react';
+import { Button } from '@/components/ui/button';
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
+import { Badge } from '@/components/ui/badge';
+import { CircleCheck, CircleAlert, RefreshCw, Database } from 'lucide-react';
+import {
+ testSupabaseConnection,
+ checkSupabaseEnvironment,
+ checkSupabaseTables
+} from '@/utils/supabaseTest';
+
+const SupabaseTestPanel = () => {
+ const [loading, setLoading] = useState(false);
+ const [connectionStatus, setConnectionStatus] = useState<{
+ tested: boolean;
+ success?: boolean;
+ message?: string;
+ }>({ tested: false });
+
+ const [envStatus] = useState(() => checkSupabaseEnvironment());
+ const [tablesStatus, setTablesStatus] = useState<{
+ checked: boolean;
+ exists?: boolean;
+ tables?: string[];
+ }>({ checked: false });
+
+ const runConnectionTest = async () => {
+ setLoading(true);
+ try {
+ const result = await testSupabaseConnection();
+ setConnectionStatus({
+ tested: true,
+ success: result.success,
+ message: result.message
+ });
+
+ // 연결 성공 시 테이블도 확인
+ if (result.success) {
+ const tablesResult = await checkSupabaseTables();
+ setTablesStatus({
+ checked: true,
+ exists: tablesResult.exists,
+ tables: tablesResult.tables
+ });
+ }
+ } catch (error) {
+ setConnectionStatus({
+ tested: true,
+ success: false,
+ message: error instanceof Error ? error.message : '알 수 없는 오류'
+ });
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+ {envStatus.message} {connectionStatus.message} 확인된 테이블:
{description}
} -honggildong@example.com
-앱 버전 0.1
-+ 현재 사용 가능한 고급 설정이 없습니다. +
+