app/components/editor/flags-panel.tsx
61 lines and 5 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| FlagsPanel | 19 to 65 | 4 | 0% | WatchCRAP 20 | No data: mutation testing has not run on this repo yet |
| <anonymous:20> | 20 to 20 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| <anonymous:26> | 26 to 44 | 5 | 0% | WatchCRAP 30 | No data: mutation testing has not run on this repo yet |
| <anonymous:39> | 39 to 39 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| <anonymous:49> | 49 to 59 | 2 | 0% | WatchCRAP 6 | No data: mutation testing has not run on this repo yet |
Imports
It imports app/lib/ai.server.ts. Imported by app/routes/editor.tsx.
Source
// The editor's flags and the AI drafts kept beside the writer's own (routes/editor.tsx). Checks and
// reviewers flag; they never decide, so a flag only asks to be read, and the Owner may dismiss it.
import { Link } from "react-router";
import { Button } from "capsomer/react/button";
import { Panel } from "capsomer/react/panel";
import { Pill, Status } from "capsomer/react/status";
import { Time } from "capsomer/react/time";
import type { AiDraftSummary, ItemFinding } from "~/lib/ai.server";
type Props = {
flags: ItemFinding[];
aiDrafts: AiDraftSummary[];
canPublish: boolean;
onDismiss: (button: HTMLElement, flag: number) => void;
};
export function FlagsPanel({ flags, aiDrafts, canPublish, onDismiss }: Props) {
const openFlags = flags.filter((f) => f.status === "open").length;
return (
<Panel title="Flags and AI drafts" id="flags" count={openFlags} src={`${aiDrafts.length} AI draft${aiDrafts.length === 1 ? "" : "s"} beside yours`}>
<div className="app-stack" data-tight>
{flags.length > 0 ? (
<ul className="app-flags" aria-label="Flags">
{flags.map((f) => (
<li key={f.id}>
{f.status === "open" ? <Status tone="warn">Open</Status> : <Pill variant="secondary">Dismissed</Pill>}
<span>
{f.message}
{f.excerpt ? (
<>
{" "}
<q className="cap-muted">{f.excerpt}</q>
</>
) : null}
</span>
{f.status === "open" && canPublish ? (
<Button size="sm" onClick={(event) => onDismiss(event.currentTarget, f.id)}>
Dismiss<span className="cap-sr-only"> flag: {f.message}</span>
</Button>
) : null}
</li>
))}
</ul>
) : null}
{aiDrafts.length > 0 ? (
<ul className="app-flags" aria-label="AI drafts beside yours">
{aiDrafts.map((d) => (
<li key={d.id}>
<span>
<Link to={`ai/${d.id}`}>AI draft from {d.client}</Link>{" "}
<span className="cap-muted">
<Time at={d.createdAt} /> · {d.words} words
</span>
{d.note ? <span> · {d.note}</span> : null}
</span>
</li>
))}
</ul>
) : null}
</div>
</Panel>
);
}