Product components · @jengacore/member-summary
MemberSummary
Msingi: identity, KYC and the three balances tellers ask for first.
Msingi
JM
Jeanne Mukamana
KYC verifiedM-004211Kicukiro branch
- Savings
- 1,250,000RWF
- Shares
- 200,000RWF
- Loan outstanding
- 374,999RWFIn arrears
Install
terminal
npx shadcn@latest add @jengacore/member-summaryWithout the namespace configured: npx shadcn@latest add https://ui.jengacore.com/r/<new-york-v4|base-nova>/member-summary.json
Registry dependencies
Source
components/jc/member-summary.tsx
import * as React from "react"
import { Badge } from "@/components/ui/badge"
import { Amount } from "@/components/jc/amount"
import { IdChip } from "@/components/jc/id-chip"
import { cn } from "@/lib/utils"
export type Member = {
name: string
number: string
branch: string
initials: string
kyc: "verified" | "pending" | "expired"
}
const KYC = {
verified: { tone: "success", label: "KYC verified" },
pending: { tone: "warning", label: "KYC pending" },
expired: { tone: "danger", label: "KYC expired" },
} as const
/**
* Msingi member header for SACCO and MFI staff: identity, KYC, and the three balances tellers ask for
* first (savings, shares, loan outstanding). Balances carry no colour; states are badges.
*/
export function MemberSummary({
member,
currency,
balances,
arrears,
actions,
className,
}: {
member: Member
currency: string
balances: { savings: string; shares: string; loan: string }
/** Shows an "In arrears" badge next to the loan balance. */
arrears?: boolean
actions?: React.ReactNode
className?: string
}) {
const kyc = KYC[member.kyc]
return (
<section data-slot="member-summary" className={cn("grid gap-5 rounded-lg border border-border bg-card p-5 shadow-card contrast:border-input", className)}>
<div className="flex flex-wrap items-center gap-4">
<span className="grid size-12 place-items-center rounded-full bg-secondary text-base font-semibold text-secondary-foreground">{member.initials}</span>
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-2">
<h2 className="text-lg leading-[26px] font-semibold">{member.name}</h2>
<Badge tone={kyc.tone}>{kyc.label}</Badge>
</div>
<div className="mt-1 flex flex-wrap items-center gap-2 text-[13px] text-muted-foreground">
<IdChip id={member.number} />
<span>{member.branch}</span>
</div>
</div>
{actions ? <div className="flex flex-wrap gap-2">{actions}</div> : null}
</div>
<dl className="grid grid-cols-1 gap-4 border-t border-border pt-4 sm:grid-cols-3">
{(
[
["Savings", balances.savings],
["Shares", balances.shares],
["Loan outstanding", balances.loan],
] as const
).map(([label, value]) => (
<div key={label} className="grid gap-1">
<dt className="eyebrow">{label}</dt>
<dd className="flex items-center gap-2">
<Amount value={value} currency={currency} size="lg" />
{label === "Loan outstanding" && arrears ? <Badge tone="danger">In arrears</Badge> : null}
</dd>
</div>
))}
</dl>
</section>
)
}