Import review
ProCheck rows before they land: how many are ready, which need fixing and why, grouped by kind of problem. A suggested fix can be accepted per row or for the whole group. Loading stays locked while problems remain, unless the person chooses to leave those rows out — and it says how many that is.
Preview
Install
With the Candor CLI
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/import-review
Brings in: button, collapsible, data, locale, locked, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import * as React from "react"
import { ImportReview } from "@/components/import-review"
import type { ImportIssue } from "@/lib/data"
const found: ImportIssue[] = [
{ row: 14, field: "Repository", kind: "unknown-value", message: "Not one of acme/api, acme/web, acme/workers", value: "acme/website", suggestion: "acme/web" },
{ row: 22, field: "Repository", kind: "unknown-value", message: "Not one of acme/api, acme/web, acme/workers", value: "API", suggestion: "acme/api" },
{ row: 3, field: "Owner", kind: "invalid", message: "No active user with this email", value: "jonas@acme", suggestion: "jonas@acme.example" },
{ row: 3, field: "Rollout", kind: "invalid", message: "Not a number", value: "n/a" },
{ row: 88, field: "Flag key", kind: "duplicate", message: "Same key as an existing flag", value: "dark-mode" },
{ row: 140, field: "Flag key", kind: "missing", message: "Required", value: "" },
]
export default function Example() {
const [issues, setIssues] = React.useState(found)
const [loading, setLoading] = React.useState(false)
return (
<ImportReview
className="max-w-2xl"
total={214}
issues={issues}
target="flags in Staging"
loading={loading}
onFix={(fixes) => setIssues((all) => all.filter((i) => !fixes.includes(i)))}
onLoad={() => setLoading(true)}
/>
)
}<ImportReview>
| Prop | Type | Default | Description |
|---|---|---|---|
| totalrequired | number | — | How many rows the file has. |
| issuesrequired | ImportIssue[] | — | Problems found, one per row and field, with a suggested fix where there is one. |
| targetrequired | string | — | Where rows go, e.g. "Customers in Shop staging". |
| onFixrequired | (fixes: ImportIssue[]) => void | — | Called with the issues whose suggested fixes a person accepted, one row or a whole group. |
| onLoadrequired | (skipRows: number[]) => void | — | Called on Load with the row numbers to leave out; empty unless the person chose to skip rows with problems. |
| loading | boolean | undefined | false | Rows are being loaded; the Load button is disabled. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under importReview in <LocaleProvider strings={{ … }}>; the table is exported as importReviewStrings.
| Key | English |
|---|---|
| reviewRows | Review rows |
| ready | Ready |
| needFixing | Need fixing |
| total | Total |
| allGood | Every row checks out. |
| kindInvalid | Not valid |
| kindMissing | Missing a required value |
| kindDuplicate | Duplicates |
| kindTooLong | Too long |
| kindUnknownValue | Not an allowed value |
| applyFixes | { one: "Apply {count} fix", other: "Apply {count} fixes" } |
| row | row {row} |
| blank | (blank) |
| apply | Apply |
| more | and {count} more |
| locked | { one: "{count} row needs fixing, or choose to leave them out.", other: "{count} rows need fixing, or choose to leave them out." } |
| leaveOut | { one: "Leave out the {count} row with problems", other: "Leave out the {count} rows with problems" } |
| load | { one: "Load {count} row into {target}", other: "Load {count} rows into {target}" } |