| import { NodeType, useNodeMessages } from "@/lib/state"; |
| import { Icon } from "./icon"; |
| import { useEffect, useState } from "react"; |
| |
| export type Props = { |
| id: string; |
| selected?: boolean; |
| children: React.ReactNode; |
| type: NodeType; |
| state: string | null; |
| }; |
| |
| export function NodeRect(p: Props) { |
| const { id, selected, children, state } = p; |
| const messages = useNodeMessages(id); |
| const hasFatal = messages.some((m) => m.type === "FATAL"); |
| const hasWarning = messages.some((m) => m.type === "WARNING"); |
| const [classes, setClasses] = useState<string[]>([]); |
| const [stateClasses, setStateClasses] = useState<string[]>([]); |
| useEffect(() => { |
| const classes = ["px-4", "py-2", "rounded-md", "bg-white"]; |
| if (hasFatal) { |
| classes.push("border-red-500"); |
| } else if (hasWarning) { |
| classes.push("border-yellow-500"); |
| } else { |
| classes.push("border-black"); |
| } |
| if (selected) { |
| classes.push("border-2"); |
| } else { |
| classes.push("border"); |
| } |
| setClasses(classes); |
| const stateClasses: string[] = []; |
| if (state === "processing") { |
| stateClasses.push("bg-yellow-500"); |
| stateClasses.push("animate-pulse"); |
| } else if (state === "success") { |
| stateClasses.push("bg-green-500"); |
| } else if (state === "failure") { |
| stateClasses.push("bg-red-500"); |
| } else { |
| stateClasses.push("bg-black"); |
| } |
| setStateClasses(stateClasses); |
| }, [selected, hasFatal, hasWarning, state, setClasses, setStateClasses]); |
| return ( |
| <div className={classes.join(" ")}> |
| <div style={{ position: "absolute", top: "5px", left: "5px" }}> |
| <Icon type={p.type} /> |
| </div> |
| <div |
| style={{ |
| position: "absolute", |
| top: "5px", |
| right: "5px", |
| borderRadius: "50%", |
| width: "5px", |
| height: "5px", |
| }} |
| className={stateClasses.join(" ")} |
| ></div> |
| {children} |
| </div> |
| ); |
| } |