import { useState, useEffect } from 'react'; import { useParams, Link } from 'react-router-dom'; import { Grove, Tree } from '../types'; import { getGrove, listTrees, createTree } from '../api'; import './Home.css'; function GrovePage() { const { groveName } = useParams<{ groveName: string }>(); const [grove, setGrove] = useState(null); const [trees, setTrees] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showForm, setShowForm] = useState(false); const [newTree, setNewTree] = useState({ name: '', description: '' }); const [creating, setCreating] = useState(false); useEffect(() => { if (groveName) { loadData(); } }, [groveName]); async function loadData() { try { setLoading(true); const [groveData, treesData] = await Promise.all([ getGrove(groveName!), listTrees(groveName!), ]); setGrove(groveData); setTrees(treesData); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load data'); } finally { setLoading(false); } } async function handleCreateTree(e: React.FormEvent) { e.preventDefault(); try { setCreating(true); await createTree(groveName!, newTree); setNewTree({ name: '', description: '' }); setShowForm(false); loadData(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create tree'); } finally { setCreating(false); } } if (loading) { return
Loading...
; } if (!grove) { return
Grove not found
; } return (

{grove.name}

{grove.description &&

{grove.description}

}
{error &&
{error}
} {showForm && (

Create New Tree

setNewTree({ ...newTree, name: e.target.value })} placeholder="releases" required />
setNewTree({ ...newTree, description: e.target.value })} placeholder="Optional description" />
)} {trees.length === 0 ? (

No trees yet. Create your first tree to start uploading artifacts!

) : (
{trees.map((tree) => (

📦 {tree.name}

{tree.description &&

{tree.description}

}
Created {new Date(tree.created_at).toLocaleDateString()}
))}
)}
); } export default GrovePage;