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
+67
View File
@@ -0,0 +1,67 @@
"use client"
import { useDataClient } from "@conusai-kit/ui/data"
import { type ResourceColumn, ResourceList } from "@conusai-kit/ui/patterns"
import { Button } from "@conusai-kit/ui/primitives"
import { useState } from "react"
import type { LedgerLabels } from "./labels.js"
/** Cursor reads happen only on user action; no local financial persistence. */
export function LedgerList<T extends object>({
seed,
procedure,
input,
columns,
rowId,
href,
labels,
title,
}: {
seed: { rows: T[]; after?: string | undefined }
procedure: string
input: Record<string, unknown>
columns: ResourceColumn<T>[]
rowId: (row: T) => string
href?: ((row: T) => string) | undefined
labels: LedgerLabels
title: string
}) {
const client = useDataClient()
const [page, setPage] = useState(seed)
const [busy, setBusy] = useState(false)
const [failed, setFailed] = useState(false)
return (
<>
<ResourceList
label={title}
data={page.rows}
columns={columns}
rowId={rowId}
rowHref={href}
rowLabel={rowId}
rowLinkLabel={() => labels.open}
empty={{ title: labels.empty }}
/>
{failed ? <p role="alert">{labels.unavailable}</p> : null}
{page.after ? (
<Button
disabled={busy}
onClick={async () => {
setBusy(true)
setFailed(false)
try {
const next = (await client.call<typeof seed>(procedure, { ...input, after: page.after })).value
setPage({ ...next, rows: [...page.rows, ...next.rows] })
} catch {
setFailed(true)
} finally {
setBusy(false)
}
}}
>
{labels.more}
</Button>
) : null}
</>
)
}