"use client";
import type { AdapterResult, RegistryAvailability } from "../types";
import { CommercialEmptyState } from "./CommercialEmptyState";
import {
commercialEntityName,
fieldLabel,
friendlyMessage,
getRegistryPresentation,
isTechnicalField,
presentValue,
registryKindForField,
} from "../presentation";
function availabilityLabel(a: RegistryAvailability): string {
switch (a) {
case "loading":
return "در حال بارگذاری…";
case "empty":
return "خالی";
case "unavailable":
return "در دسترس نیست";
case "permission_denied":
return "بدون دسترسی";
case "error":
return "خطا";
default:
return "";
}
}
function PresentedValue({ value, contextKey }: { value: unknown; contextKey?: string }) {
const presented = presentValue(value);
if (Array.isArray(presented)) {
return (
{presented.map((item, index) => (
typeof item === "string" ? (
{item}
) : (
)
))}
);
}
if (presented && typeof presented === "object") {
const entries = Object.entries(presented).filter(([key]) => !isTechnicalField(key));
const referencedKind = registryKindForField(contextKey);
const codeEntry = Object.entries(presented).find(([key]) => /(^code$|_code$)/.test(key));
const explicitName =
typeof presented.display_name === "string"
? presented.display_name
: typeof presented.title === "string"
? presented.title
: null;
const objectTitle =
referencedKind && codeEntry
? commercialEntityName(referencedKind, codeEntry[1], explicitName)
: null;
return (
{objectTitle || "مشاهده جزئیات"}
{entries.map(([key, nested]) => (
))}
);
}
return <>{presented}>;
}
/** Generic human-facing catalog list. Implementation identifiers are deliberately hidden. */
export function RegistryBrowser({
kind,
title,
subtitle,
result,
codeKey,
nameKey = "display_name",
emptyTitle,
}: {
kind: string;
title?: string;
subtitle?: string;
result: AdapterResult | null;
codeKey: string;
nameKey?: string;
emptyTitle?: string;
}) {
const presentation = getRegistryPresentation(kind);
const sectionTitle = title || presentation.sectionTitle;
if (!result || result.availability === "loading") {
return (
{sectionTitle}
{availabilityLabel("loading")}
);
}
if (result.availability !== "ready" || !result.data.length) {
return (
{sectionTitle}
{subtitle ? {subtitle}
: null}
);
}
return (
{sectionTitle}
{subtitle ? {subtitle}
: null}
{result.data.map((raw, idx) => {
const item = (raw && typeof raw === "object" ? raw : {}) as Record;
const code = String(item[codeKey] ?? idx);
const explicitName = typeof item[nameKey] === "string" ? String(item[nameKey]) : null;
const name = commercialEntityName(kind, code, explicitName);
const meta = item.metadata;
const detailEntries = Object.entries(item).filter(
([key, value]) =>
key !== codeKey &&
key !== nameKey &&
key !== "metadata" &&
!isTechnicalField(key) &&
value != null
);
return (
-
{name}
{detailEntries.length ? (
{detailEntries.slice(0, 4).map(([key, value]) => (
))}
) : null}
{meta && typeof meta === "object" && !Array.isArray(meta) ? (
) : null}
);
})}
);
}
/** Renders an arbitrary metadata bag without whitelisting attribute keys. */
export function MetadataBagView({
title,
attributes,
message,
availability,
}: {
title: string;
attributes?: Record | null;
message?: string;
availability?: RegistryAvailability;
}) {
const entries = attributes ? Object.entries(attributes) : [];
if (!entries.length) {
return (
);
}
return (
{title}
{entries.filter(([key]) => !isTechnicalField(key)).map(([key, value]) => (
))}
);
}