import { useState, useEffect, useRef } from 'react'; import { useParams, Link } from 'react-router-dom'; import { Graft } from '../types'; import { listGrafts, cultivate, getDownloadUrl } from '../api'; import './Home.css'; import './TreePage.css'; function TreePage() { const { groveName, treeName } = useParams<{ groveName: string; treeName: string }>(); const [grafts, setGrafts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [uploading, setUploading] = useState(false); const [uploadResult, setUploadResult] = useState(null); const [tag, setTag] = useState(''); const fileInputRef = useRef(null); useEffect(() => { if (groveName && treeName) { loadGrafts(); } }, [groveName, treeName]); async function loadGrafts() { try { setLoading(true); const data = await listGrafts(groveName!, treeName!); setGrafts(data); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load grafts'); } finally { setLoading(false); } } async function handleUpload(e: React.FormEvent) { e.preventDefault(); const file = fileInputRef.current?.files?.[0]; if (!file) { setError('Please select a file'); return; } try { setUploading(true); setError(null); const result = await cultivate(groveName!, treeName!, file, tag || undefined); setUploadResult(`Uploaded successfully! Fruit ID: ${result.fruit_id}`); setTag(''); if (fileInputRef.current) { fileInputRef.current.value = ''; } loadGrafts(); } catch (err) { setError(err instanceof Error ? err.message : 'Upload failed'); } finally { setUploading(false); } } if (loading) { return
Loading...
; } return (

📦 {treeName}

{error &&
{error}
} {uploadResult &&
{uploadResult}
}

Upload Artifact

setTag(e.target.value)} placeholder="v1.0.0, latest, stable..." />

Tags / Versions

{grafts.length === 0 ? (

No tags yet. Upload an artifact with a tag to create one!

) : (
{grafts.map((graft) => ( ))}
Tag Fruit ID Created Actions
{graft.name} {graft.fruit_id.substring(0, 12)}... {new Date(graft.created_at).toLocaleString()} Download
)}

Usage

Download artifacts using:

          curl -O {window.location.origin}/api/v1/grove/{groveName}/{treeName}/+/latest
        

Or with a specific tag:

          curl -O {window.location.origin}/api/v1/grove/{groveName}/{treeName}/+/v1.0.0
        
); } export default TreePage;