import React from "react"; import { IntentLink } from "sanity/router"; import { Spinner } from "@sanity/ui"; import { EditIcon, CheckmarkCircleIcon, LaunchIcon, ChevronDownIcon, WarningOutlineIcon, } from "@sanity/icons"; import { scoreColor, scoreLabel } from "../bulk/types"; import { WorkflowDoc, WorkflowStatus, STATUS_CFG } from "./types"; interface Props { doc: WorkflowDoc; isOpen: boolean; onToggle: () => void; patching: boolean; onPatch: (doc: WorkflowDoc, status: WorkflowStatus) => void; onSaveNotes: (doc: WorkflowDoc, notes: string) => Promise; } export default function WorkflowRow({ doc, isOpen, onToggle, patching, onPatch, onSaveNotes, }: Props) { const cfg = STATUS_CFG[doc.seoStatus] || STATUS_CFG.draft; const StatusIcon = cfg.Icon; const issueCount = doc.issues.length; const scoreCol = scoreColor(doc.score); const [hovered, setHovered] = React.useState(false); const [notes, setNotes] = React.useState(doc.reviewNotes || ""); const [savingNotes, setSavingNotes] = React.useState(false); const [notesSaved, setNotesSaved] = React.useState(false); const handleSaveNotes = async () => { setSavingNotes(true); setNotesSaved(false); await onSaveNotes(doc, notes); setSavingNotes(false); setNotesSaved(true); setTimeout(() => setNotesSaved(false), 2500); }; return (
setHovered(true)} onMouseLeave={() => setHovered(false)} >
e.key === "Enter" && onToggle()} style={{ display: "grid", gridTemplateColumns: "90px 1fr 60px 160px auto", gap: 14, alignItems: "center", padding: "13px 16px", cursor: "pointer", }} >
{doc.score}
{scoreLabel(doc.score)}
{doc.docTitle}
{new Date(doc._updatedAt).toLocaleDateString(undefined, { month: "short", day: "numeric", year: "numeric", })} {issueCount > 0 && ( {issueCount} issue{issueCount !== 1 ? "s" : ""} )} {issueCount === 0 && ( No issues )}
{doc._type}
{cfg.label}
{isOpen && (
)}
); } function SectionHeader({ icon: Icon, title, sub, }: { // eslint-disable-next-line @typescript-eslint/no-explicit-any icon: React.ComponentType; title: string; sub?: string; }) { return (
{title} {sub && ( {sub} )}
); } function IssuesSection({ issues }: { issues: string[] }) { return (
{issues.length === 0 ? (
All SEO checks pass — this document is ready to approve.
) : (
{issues.map((issue) => ( {issue} ))}
)}
); } function NotesSection({ notes, seoStatus, savedNotes, savingNotes, notesSaved, onNotesChange, onSaveNotes, }: { notes: string; seoStatus: WorkflowStatus; savedNotes: string; savingNotes: boolean; notesSaved: boolean; onNotesChange: (v: string) => void; onSaveNotes: () => void; }) { const isDisabled = savingNotes || notes === savedNotes; return (