Files
AgentCompany/src/renderer/components/automation/RuleCard.tsx
T
2026-03-30 00:15:21 -04:00

36 lines
3.9 KiB
TypeScript

import { motion } from "framer-motion"
import { ArrowRight, CaretRight, Gear, Lightning, Pause, Play, Trash } from "@phosphor-icons/react"
import type { AutomationRuleRecord } from "@shared/types"
import { timeAgo } from "../../lib/formatters"
import { ACCENT, LINE, triggerConfig, actionConfig, statusColors } from "./automation-config"
export function RuleCard({ rule, onToggle, onDelete, onEdit }: { rule: AutomationRuleRecord; onToggle: () => void; onDelete: () => void; onEdit: () => void }) {
const triggerInfo = triggerConfig[rule.trigger]; const actionInfo = actionConfig[rule.action]
const TriggerIcon = triggerInfo?.icon ?? Lightning; const colors = statusColors[rule.status]
return (
<motion.div layout initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, x: 20 }} className="group rounded-lg border bg-card transition duration-150 hover:shadow-md hover:-translate-y-px" style={{ borderColor: LINE }}>
<div className="flex items-center gap-3 px-4 py-3.5">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg" style={{ backgroundColor: `${ACCENT}12`, color: ACCENT }}><TriggerIcon size={20} weight="fill" /></div>
<button type="button" onClick={onEdit} className="min-w-0 flex-1 text-left">
<div className="flex items-center gap-2">
<span className="truncate text-[13px] font-bold text-foreground">{rule.name}</span>
<span className="flex shrink-0 items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[9px] font-bold uppercase tracking-[0.1em]" style={{ backgroundColor: colors.bg, color: colors.text }}><span className="h-1.5 w-1.5 rounded-full" style={{ backgroundColor: colors.dot }} aria-hidden="true" />{rule.status}</span>
</div>
<div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground">
<span className="inline-flex items-center gap-1 rounded-[4px] bg-muted px-1.5 py-0.5 font-medium text-muted-foreground"><Lightning size={10} weight="fill" />{triggerInfo?.label ?? rule.trigger}</span>
<ArrowRight size={10} className="text-muted-foreground" />
<span className="inline-flex items-center gap-1 rounded-[4px] bg-muted px-1.5 py-0.5 font-medium text-muted-foreground"><Gear size={10} />{actionInfo?.label ?? rule.action}</span>
{rule.sourceDepartment || rule.targetDepartment ? <><span className="text-[color:var(--border)]">|</span><span className="inline-flex items-center gap-1"><span className="font-medium text-muted-foreground">{rule.sourceDepartment ?? "Any"}</span><CaretRight size={8} /><span className="font-medium text-muted-foreground">{rule.targetDepartment ?? "Same"}</span></span></> : null}
</div>
<div className="mt-1 flex items-center gap-3 text-[10px] text-muted-foreground"><span className="tabular-nums">{rule.executionCount} execution{rule.executionCount !== 1 ? "s" : ""}</span><span className="h-0.5 w-0.5 rounded-full bg-[color:var(--muted-foreground)]" /><span>Last run {timeAgo(rule.lastExecutedAt)}</span><span className="h-0.5 w-0.5 rounded-full bg-[color:var(--muted-foreground)]" /><span className="tabular-nums">Priority {rule.priority}</span></div>
</button>
<div className="flex shrink-0 items-center gap-1">
<button type="button" onClick={onToggle} aria-label={rule.status === "active" ? "Pause rule" : "Activate rule"} title={rule.status === "active" ? "Pause rule" : "Activate rule"} className="rounded-lg p-2 text-muted-foreground transition hover:bg-muted hover:text-foreground">{rule.status === "active" ? <Pause size={15} /> : <Play size={15} />}</button>
<button type="button" onClick={onDelete} aria-label="Delete rule" title="Delete rule" className="rounded-lg p-2 text-muted-foreground opacity-0 transition hover:bg-destructive-muted hover:text-destructive group-hover:opacity-100"><Trash size={15} /></button>
</div>
</div>
</motion.div>
)
}