"use client"; import { motion, AnimatePresence } from "motion/react"; import { useEffect, useState } from "react"; import ActionMenu from "./action-menu"; import { invoke } from "@tauri-apps/api/core"; type App = { id: string; name: string; description?: string; address: string; ssh_addr?: string; }; interface Props { app: App; } type PingStatus = "success" | "error" | "loading"; export default function AppCard({ app }: Props) { const [pingStatus, setPingStatus] = useState("loading"); const [hovered, setHovered] = useState(false); let pingColor = pingStatus === "success" ? "bg-green-500" : pingStatus === "error" ? "bg-red-500" : "bg-gray-500"; const pingApp = async (): Promise => { let status: boolean = await invoke("ping", { address: app.address }); return status; }; useEffect(() => { let isMounted = true; const performPing = async () => { setPingStatus("loading"); try { // Since we simplified the Rust command to return a bool, we just read the result const success = await invoke("ping", { address: app.address }); if (isMounted) { setPingStatus(success ? "success" : "error"); } } catch (err) { if (isMounted) { setPingStatus("error"); } } }; performPing(); // Optional: Set up an interval if you want it to poll periodically const interval = setInterval(performPing, 10000); // Poll every 10 seconds return () => { isMounted = false; clearInterval(interval); }; }, [app.address]); return (
setHovered(true)} onMouseLeave={() => setHovered(false)} className={` relative rounded-2xl bg-gray-100 p-3 ${hovered && "border bg-white"} transition-all duration-200 `} >

{app.name}

{app.address} {hovered && ( {app.description && ( {app.description} )} )}
); }