54545
This commit is contained in:
@@ -1,11 +1,53 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import API_CONFIG from './api/config';
|
||||
|
||||
function App() {
|
||||
const [apiStatus, setApiStatus] = useState('Checking...');
|
||||
const [apiUrl, setApiUrl] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
// Показыва какой API URL используется
|
||||
const baseUrl = API_CONFIG.getBaseUrl();
|
||||
const fullUrl = `${window.location.origin}${baseUrl}`;
|
||||
setApiUrl(fullUrl);
|
||||
|
||||
// Проверяем подключение к API
|
||||
const checkAPI = async () => {
|
||||
try {
|
||||
const response = await fetch(`${baseUrl}/health`, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setApiStatus('✅ Connected');
|
||||
} else {
|
||||
setApiStatus(`⚠️ Error: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
setApiStatus(`❌ Failed: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
checkAPI();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
|
||||
<h1>PostgreSQL Admin Panel</h1>
|
||||
<p>Frontend is loading...</p>
|
||||
<p>API Status: <span id="status">Checking...</span></p>
|
||||
<p>Frontend is ready! 🚀</p>
|
||||
<hr />
|
||||
<h3>🔌 API Configuration</h3>
|
||||
<p><strong>API Base URL:</strong> {apiUrl}</p>
|
||||
<p><strong>API Status:</strong> {apiStatus}</p>
|
||||
<hr />
|
||||
<h3>💡 How it works:</h3>
|
||||
<ul>
|
||||
<li>✅ Frontend automatically detects API URL from window.location</li>
|
||||
<li>✅ Nginx proxies /api/* to backend internally</li>
|
||||
<li>✅ Works on localhost, IP, or domain without configuration</li>
|
||||
<li>✅ No hardcoded environment variables needed for API URL</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
44
frontend/src/api/config.js
Normal file
44
frontend/src/api/config.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// Автоматическое определение API URL без необходимости env переменных
|
||||
// Работает на localhost, IP адресе или доменном имени
|
||||
|
||||
const API_CONFIG = {
|
||||
// Определяй базовый URL на основе текущего location
|
||||
// Фронтенд обращается к /api, nginx перенаправляет на backend внутри Docker сети
|
||||
getBaseUrl: () => {
|
||||
// Используем относительный путь /api вместо абсолютного URL
|
||||
// Например: http://localhost:3000/api или http://185.56.162.170:8080/api
|
||||
return '/api';
|
||||
},
|
||||
|
||||
// Получить полный URL для API запроса
|
||||
getApiUrl: (endpoint) => {
|
||||
const baseUrl = API_CONFIG.getBaseUrl();
|
||||
// Убираем слэш в начале endpoint если есть
|
||||
const cleanEndpoint = endpoint.startsWith('/') ? endpoint.slice(1) : endpoint;
|
||||
return `${baseUrl}/${cleanEndpoint}`;
|
||||
},
|
||||
|
||||
// Хелпер для fetch запросов
|
||||
fetch: async (endpoint, options = {}) => {
|
||||
const url = API_CONFIG.getApiUrl(endpoint);
|
||||
const defaultHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...options.headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`API Error: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
},
|
||||
};
|
||||
|
||||
export default API_CONFIG;
|
||||
59
frontend/src/components/ExampleAPIUsage.js
Normal file
59
frontend/src/components/ExampleAPIUsage.js
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @example Пример использования API конфига в React компоненте
|
||||
*
|
||||
* import API_CONFIG from './api/config';
|
||||
*
|
||||
* function MyComponent() {
|
||||
* useEffect(() => {
|
||||
* // Вариант 1: Простой fetch
|
||||
* fetch(API_CONFIG.getApiUrl('users'))
|
||||
* .then(r => r.json())
|
||||
* .then(data => console.log(data));
|
||||
*
|
||||
* // Вариант 2: Использовать хелпер API_CONFIG.fetch
|
||||
* API_CONFIG.fetch('users')
|
||||
* .then(data => console.log(data))
|
||||
* .catch(error => console.error(error));
|
||||
*
|
||||
* // Вариант 3: С параметрами
|
||||
* API_CONFIG.fetch('users/123', {
|
||||
* method: 'GET',
|
||||
* });
|
||||
*
|
||||
* // Вариант 4: POST запрос
|
||||
* API_CONFIG.fetch('users', {
|
||||
* method: 'POST',
|
||||
* body: JSON.stringify({ name: 'John' }),
|
||||
* });
|
||||
* }, []);
|
||||
* }
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import API_CONFIG from '../api/config';
|
||||
|
||||
function ExampleComponent() {
|
||||
const [data, setData] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Получи данные с API
|
||||
API_CONFIG.fetch('users')
|
||||
.then(data => setData(data))
|
||||
.catch(err => setError(err.message))
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
if (loading) return <p>Loading...</p>;
|
||||
if (error) return <p>Error: {error}</p>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Users from API</h2>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExampleComponent;
|
||||
Reference in New Issue
Block a user