ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
"use client"
import { Button } from "@conusai-kit/ui/primitives"
// Adds a retention class. A class never changes once it exists: a new policy is a new class.
import type { ProjectSlugs } from "@conusai-kit/ui"
import { describeError, useWrite } from "@conusai-kit/ui/data"
import { SelectField, serviceNotice, usePageNavigation } from "@conusai-kit/ui/patterns"
import { Alert, AlertDescription, Field, FieldDescription, FieldLabel, Input } from "@conusai-kit/ui/primitives"
import { type FormEvent, type ReactElement, useState } from "react"
import { RETENTION_BASES, type RetentionClassView } from "../contract/index.js"
export interface RetentionFormLabels {
readonly heading: string
readonly code: string
readonly keepFor: string
readonly keepForHint: string
readonly from: string
readonly submit: string
readonly busy: string
readonly bases: Readonly<Record<RetentionClassView["from"], string>>
readonly failed: string
/** The text of each business refusal by problem code (`businessRefusalNotices` of `@conusai-kit/business/refusals`). */
readonly refusals: Readonly<Record<string, string>>
}
export function RetentionForm({ slugs, labels }: { slugs: ProjectSlugs; labels: RetentionFormLabels }): ReactElement {
const navigation = usePageNavigation()
const create = useWrite<Record<string, unknown>, unknown>("archive.retention.create")
const [requestId, setRequestId] = useState(() => crypto.randomUUID())
const [state, setState] = useState<{ kind: "idle" | "busy" } | { kind: "failed"; detail: string }>({ kind: "idle" })
const submit = async (event: FormEvent<HTMLFormElement>): Promise<void> => {
event.preventDefault()
const form = new FormData(event.currentTarget)
setState({ kind: "busy" })
try {
await create.mutate({
...slugs,
code: String(form.get("code") ?? "").trim(),
keepFor: String(form.get("keepFor") ?? "").trim(),
from: String(form.get("from") ?? "created"),
requestId,
})
await navigation.refresh()
setRequestId(crypto.randomUUID())
setState({ kind: "idle" })
} catch (error) {
setState({ kind: "failed", detail: serviceNotice(error, labels.refusals)?.text ?? describeError(error) })
}
}
return (
<form key={requestId} onSubmit={submit} aria-busy={state.kind === "busy"}>
<h2>{labels.heading}</h2>
<Field>
<FieldLabel>{labels.code}</FieldLabel>
<Input name="code" type="text" required maxLength={64} pattern="[A-Za-z0-9_\-]+" />
</Field>
<Field>
<FieldLabel>{labels.keepFor}</FieldLabel>
<Input name="keepFor" type="text" required maxLength={64} />
<FieldDescription>{labels.keepForHint}</FieldDescription>
</Field>
<SelectField
name="from"
label={labels.from}
defaultValue="created"
options={RETENTION_BASES.map((base) => ({ value: base, label: labels.bases[base] }))}
/>
<Button type="submit" disabled={state.kind === "busy"}>
{state.kind === "busy" ? labels.busy : labels.submit}
</Button>
{state.kind === "failed" ? (
<Alert variant="destructive">
<AlertDescription>{labels.failed.replace("{detail}", state.detail)}</AlertDescription>
</Alert>
) : null}
</form>
)
}