import React, { useState, useEffect, useMemo } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { ArrowLeft, Download, Star, Calendar, Package, ExternalLink, Tag, Server } from 'lucide-react'; import { colors } from '../../theme/colors'; import { Dropdown } from '../../components/dashboardPrimitives'; import { API_BASE_URL, WS_BASE_URL as WS_URL } from '../../config/api'; import branding from '../../branding'; function PluginDetails() { const { pluginId } = useParams(); const navigate = useNavigate(); const [plugin, setPlugin] = useState(null); const [versions, setVersions] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [selectedVersion, setSelectedVersion] = useState(null); const [servers, setServers] = useState([]); const [selectedServer, setSelectedServer] = useState(null); const [downloadingToServer, setDownloadingToServer] = useState(false); const [downloadStatus, setDownloadStatus] = useState(''); const serverDropdownOptions = useMemo( () => servers.map((server) => ({ value: server.id, label: server.name })), [servers], ); useEffect(() => { const fetchPluginDetails = async () => { setLoading(true); setError(''); try { // Fetch project 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(); setPlugin(projectData); // Fetch versions const versionsResponse = await fetch( `${API_BASE_URL}/api/modrinth/project/${pluginId}/versions` ); if (versionsResponse.ok) { const versionsData = await versionsResponse.json(); setVersions(versionsData); if (versionsData.length > 0) { setSelectedVersion(versionsData[0]); } } } catch (err) { setError(err.message); console.error('Error fetching plugin details:', err); } finally { setLoading(false); } }; const fetchServers = async () => { try { const token = localStorage.getItem('anchorhost_token'); if (!token) return; const ws = new WebSocket(`${WS_URL}?token=${token}`); ws.onopen = () => { ws.send(JSON.stringify({ type: 'get_servers' })); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'servers_list') { // Filter only Minecraft servers const minecraftServers = (data.servers || []).filter( server => server.image === 'minecraft' && server.type === 'game' ); setServers(minecraftServers); ws.close(); } }; ws.onerror = (error) => { console.error('WebSocket error:', error); ws.close(); }; } catch (err) { console.error('Error fetching servers:', err); } }; if (pluginId) { fetchPluginDetails(); fetchServers(); } }, [pluginId]); const formatDate = (dateString) => { if (!dateString) return 'Unknown'; const date = new Date(dateString); return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); }; const handleDownload = () => { if (selectedVersion && selectedVersion.files && selectedVersion.files.length > 0) { const primaryFile = selectedVersion.files.find(f => f.primary) || selectedVersion.files[0]; window.open(primaryFile.url, '_blank'); } }; const handleDownloadToServer = async () => { if (!selectedServer || !selectedVersion) { setError('Please select a server 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: selectedServer.id, plugin_url: primaryFile.url, plugin_name: plugin.title || pluginId, file_name: primaryFile.filename || `${pluginId}.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(''); } }; if (loading) { return (
{error || 'Plugin not found'}
by {plugin.team || (plugin.team_data && plugin.team_data.name) || 'Unknown'}
{typeof plugin.description === 'string' ? new DOMParser().parseFromString(plugin.description, 'text/html').body.textContent : ''}