import React, { useState, useEffect, useCallback } from 'react'; import { Search, Download, RefreshCw, Package, AlertTriangle, ArrowLeft, Filter } from "lucide-react"; import { colors, Dropdown, SectionCard, minecraftVersions } from '../../components/DashboardComponents'; import { API_BASE_URL } from '../../config/api'; import branding from '../../branding'; // Embedded Plugin Store Component for Dashboard const PluginStoreEmbedded = ({ serverId }) => { const [plugins, setPlugins] = useState([]); const [loading, setLoading] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [selectedGameVersion, setSelectedGameVersion] = useState(''); const [currentPage, setCurrentPage] = useState(0); const [error, setError] = useState(''); const [selectedPlugin, setSelectedPlugin] = useState(null); const [pluginDetails, setPluginDetails] = useState(null); const [pluginVersions, setPluginVersions] = useState([]); const [selectedVersion, setSelectedVersion] = useState(null); const [downloadingToServer, setDownloadingToServer] = useState(false); const [downloadStatus, setDownloadStatus] = useState(''); const [loadingDetails, setLoadingDetails] = useState(false); const [totalResults, setTotalResults] = useState(0); const handlePluginClick = async (pluginId) => { setSelectedPlugin(pluginId); setError(''); setLoadingDetails(true); try { // Fetch plugin details const projectResponse = await fetch( `${API_BASE_URL}/api/modrinth/project/${pluginId}`, { headers: { 'User-Agent': `${branding.name}/1.0` } } ); if (!projectResponse.ok) { throw new Error('Failed to fetch plugin details'); } const projectData = await projectResponse.json(); setPluginDetails(projectData); // Fetch versions const versionsResponse = await fetch( `${API_BASE_URL}/api/modrinth/project/${pluginId}/versions` ); if (versionsResponse.ok) { const versionsData = await versionsResponse.json(); setPluginVersions(versionsData); if (versionsData.length > 0) { setSelectedVersion(versionsData[0]); } } } catch (err) { setError(err.message); console.error('Error fetching plugin details:', err); } finally { setLoadingDetails(false); } }; const handleBackToList = () => { setSelectedPlugin(null); setPluginDetails(null); setPluginVersions([]); setSelectedVersion(null); setError(''); }; const handleDownloadToServer = async () => { if (!serverId || !selectedVersion) { setError('Please select a version first'); return; } if (!selectedVersion.files || selectedVersion.files.length === 0) { setError('No file available for this version'); return; } const primaryFile = selectedVersion.files.find(f => f.primary) || selectedVersion.files[0]; setDownloadingToServer(true); setDownloadStatus('Downloading plugin...'); try { const token = localStorage.getItem('anchorhost_token'); if (!token) { throw new Error('Not authenticated'); } const response = await fetch(`${API_BASE_URL}/api/plugins/download-to-server`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ server_id: serverId, plugin_url: primaryFile.url, plugin_name: pluginDetails?.title || selectedPlugin, file_name: primaryFile.filename || `${selectedPlugin}.jar` }) }); const result = await response.json(); if (!response.ok) { throw new Error(result.error || 'Failed to download plugin to server'); } setDownloadStatus('Plugin downloaded successfully!'); setTimeout(() => { setDownloadStatus(''); setDownloadingToServer(false); }, 3000); } catch (err) { setError(err.message); setDownloadingToServer(false); setDownloadStatus(''); } }; const gameVersions = [ { value: '', label: 'All Versions' }, ...minecraftVersions.flatMap(series => series.versions.map(v => ({ value: v, label: v })) ) ]; const searchPlugins = useCallback(async (query = '', page = 0) => { setLoading(true); setError(''); try { const params = new URLSearchParams({ query: query || '', limit: '20', offset: (page * 20).toString(), project_type: 'plugin' }); if (selectedGameVersion) { params.append('game_versions', selectedGameVersion); } const response = await fetch(`${API_BASE_URL}/api/modrinth/search?${params.toString()}`); if (!response.ok) { throw new Error('Failed to search plugins'); } const data = await response.json(); setPlugins(data.hits || []); setTotalResults(data.total_hits || 0); } catch (err) { setError(err.message); console.error('Error searching plugins:', err); } finally { setLoading(false); } }, [selectedGameVersion]); useEffect(() => { searchPlugins(searchQuery, currentPage); }, [searchPlugins, searchQuery, currentPage]); const handleSearch = (e) => { e.preventDefault(); setCurrentPage(0); searchPlugins(searchQuery, 0); }; if (loadingDetails) { return (
); } if (selectedPlugin && pluginDetails) { return (
{pluginDetails.title}

{pluginDetails.description}

Downloads {pluginDetails.downloads.toLocaleString()}
Last Update {new Date(pluginDetails.updated).toLocaleDateString()}
{pluginVersions.map((version) => (
setSelectedVersion(version)} className={`p-5 rounded-2xl border transition-all duration-300 group cursor-pointer ${ selectedVersion?.id === version.id ? 'bg-blue-500/10' : 'bg-black/20 hover:bg-white/5' }`} style={{ borderColor: selectedVersion?.id === version.id ? colors.blue : colors.brightBlack }} >
{version.name} {version.version_number}
{version.game_versions.slice(0, 5).map(gv => ( {gv} ))} {version.game_versions.length > 5 && +{version.game_versions.length - 5} more}
))}
{downloadStatus && (
{downloadStatus}
)}
); } return (
setSearchQuery(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch(e)} className="w-full pl-11 pr-4 py-3 rounded-xl bg-black/40 border text-white placeholder:text-white/50 focus:border-primary/50 focus:bg-black/60 focus:outline-none transition-all font-medium text-sm" style={{ borderColor: colors.brightBlack }} />
{loading ? (
Searching Modrinth...
) : error ? (

Search Error

{error}

) : plugins.length === 0 ? (

No Plugins Found

Try broadening your search or changing the version filter.

) : (
{plugins.map((plugin) => (
handlePluginClick(plugin.slug)} className="p-5 rounded-xl border transition-all cursor-pointer group flex flex-col h-full" style={{ backgroundColor: colors.brightBlack, borderColor: colors.brightBlack }} >
{plugin.title}

{plugin.title}

{plugin.author}

{plugin.description}

{plugin.downloads.toLocaleString()}
))}
)}
); }; export default PluginStoreEmbedded;