"use client"; import React, { useState, useEffect, useCallback } from 'react'; import { post } from '@/services/api'; // Define styles locally const btnSecondaryStyles = "px-3 py-1 text-xs bg-gray-200 text-gray-800 font-semibold rounded-lg shadow-md hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600 disabled:opacity-50 transition-colors"; interface XrayGeoManagementModalProps { isOpen: boolean; onClose: () => void; currentXrayVersion: string | undefined; onActionComplete: () => Promise; // Callback to refresh dashboard status } const GEO_FILES_LIST = [ "geoip.dat", "geosite.dat", "geoip_IR.dat", "geosite_IR.dat", ]; const XrayGeoManagementModal: React.FC = ({ isOpen, onClose, currentXrayVersion, onActionComplete }) => { const [xrayVersions, setXrayVersions] = useState([]); const [isLoadingVersions, setIsLoadingVersions] = useState(false); const [isInstalling, setIsInstalling] = useState(null); const [isUpdatingFile, setIsUpdatingFile] = useState(null); const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); const [activeTab, setActiveTab] = useState<'xray' | 'geo'>('xray'); const fetchXrayVersions = useCallback(async () => { if (!isOpen) return; // Ensure modal is open before fetching setIsLoadingVersions(true); setError(null); try { // Explicitly type the expected response structure const response = await post<{ versions?: string[], data?: string[] }>('/server/getXrayVersion', {}); if (response.success) { const versionsData = response.data; // data might be string[] or { versions: string[] } if (Array.isArray(versionsData)) { // Case: data is string[] setXrayVersions(versionsData); } else if (versionsData && Array.isArray(versionsData.versions)) { // Case: data is { versions: string[] } setXrayVersions(versionsData.versions); } else { setError('Fetched Xray versions data is not in the expected format.'); setXrayVersions([]); } } else { setError(response.message || 'Failed to fetch Xray versions.'); setXrayVersions([]); } } catch (err) { setError(err instanceof Error ? err.message : 'Unknown error fetching versions.'); setXrayVersions([]); } finally { setIsLoadingVersions(false); } }, [isOpen]); useEffect(() => { if (isOpen && activeTab === 'xray') { fetchXrayVersions(); } }, [isOpen, activeTab, fetchXrayVersions]); const handleInstallXray = async (version: string) => { if (!window.confirm(`Are you sure you want to install Xray version: ${version}?\nThis will restart Xray service.`)) return; setIsInstalling(version); setError(null); setSuccessMessage(null); let response; // Declare response here try { response = await post(`/server/installXray/${version}`, {}); if (response.success) { setSuccessMessage(response.message || `Xray ${version} installed successfully. Xray service is restarting.`); onActionComplete(); } else { setError(response.message || 'Failed to install Xray version.'); } } catch (err) { setError(err instanceof Error ? err.message : 'Unknown error during Xray installation.'); } finally { setIsInstalling(null); if (response?.success) setTimeout(() => setSuccessMessage(null), 4000); else if (error) setTimeout(() => setError(null), 4000); // Check local error state } }; const handleUpdateGeoFile = async (fileName: string) => { if (!window.confirm(`Are you sure you want to update ${fileName}?\nThis may restart Xray service if changes are detected.`)) return; setIsUpdatingFile(fileName); setError(null); setSuccessMessage(null); let response; // Declare response here try { response = await post(`/server/updateGeofile/${fileName}`, {}); if (response.success) { setSuccessMessage(response.message || `${fileName} updated successfully.`); onActionComplete(); } else { setError(response.message || `Failed to update ${fileName}.`); } } catch (err) { setError(err instanceof Error ? err.message : `Unknown error updating ${fileName}.`); } finally { setIsUpdatingFile(null); if (response?.success) setTimeout(() => setSuccessMessage(null), 4000); else if (error) setTimeout(() => setError(null), 4000); // Check local error state } }; const handleClose = () => { setError(null); setSuccessMessage(null); onClose(); }; if (!isOpen) return null; return (
e.stopPropagation()}>

Xray & Geo Management

{error &&
{error}
} {successMessage &&
{successMessage}
}
{activeTab === 'xray' && (

Current Xray Version: {currentXrayVersion || 'Unknown'}

{isLoadingVersions &&

Loading versions...

} {!isLoadingVersions && xrayVersions.length === 0 && !error &&

No versions found or failed to load.

}
    {xrayVersions.map(version => (
  • {version} {version === currentXrayVersion ? ( Current ) : ( )}
  • ))}
)} {activeTab === 'geo' && (

Manage GeoIP and GeoSite files.

    {GEO_FILES_LIST.map(fileName => (
  • {fileName}
  • ))}
)}
); }; export default XrayGeoManagementModal;