162 lines
5.8 KiB
TypeScript
162 lines
5.8 KiB
TypeScript
// * Packages
|
|
import { ReactNode } from "react";
|
|
// * Components shadcn
|
|
import {
|
|
Accordion,
|
|
AccordionContent,
|
|
AccordionItem,
|
|
AccordionTrigger,
|
|
} from "@/components/ui/accordion";
|
|
// * Other
|
|
import str from "@/hooks/use-string";
|
|
import useTrans from "@/hooks/use-translations";
|
|
import { ConfigField } from "@/back/types/dynamic-pages";
|
|
import { cn, GetTranslation } from "@/lib/utils";
|
|
|
|
type ChildItem = Record<string, string | number | object | ChildItem[]>;
|
|
|
|
const RenderRows = (
|
|
currentValue: string | number | object,
|
|
currentConfig: ConfigField[],
|
|
hasBorders: boolean = false,
|
|
path: string = "",
|
|
): ReactNode => {
|
|
const tableNotKnownTrans = str(useTrans("back.table_not_known"))
|
|
.ucFirst()
|
|
.value();
|
|
|
|
return currentConfig.map((field, index) => {
|
|
const hasChildren = !!field.children?.length;
|
|
const accordionKey = path
|
|
? `${path}.${field.key}-${index}`
|
|
: `${field.key}-${index}`;
|
|
|
|
const rowContent = (currentHasChildren: boolean = false) => {
|
|
const cellClasses = "break-words whitespace-normal";
|
|
const placeholderClasses =
|
|
"text-sm text-muted-foreground break-words whitespace-normal";
|
|
const fieldValue =
|
|
currentValue[field.key as keyof typeof currentValue];
|
|
|
|
let cellContent: ReactNode;
|
|
if (currentHasChildren) {
|
|
const count = Array.isArray(fieldValue)
|
|
? Object.values(fieldValue).length
|
|
: 0;
|
|
cellContent = (
|
|
<p className={placeholderClasses}>
|
|
{GetTranslation("back.element", {
|
|
params: { count: String(count) },
|
|
choice: count > 1 ? 2 : 1,
|
|
})}
|
|
</p>
|
|
);
|
|
} else if (fieldValue !== null && fieldValue !== undefined) {
|
|
cellContent = (
|
|
<p className={cellClasses}>
|
|
{typeof fieldValue === "boolean"
|
|
? GetTranslation(
|
|
fieldValue ? "back.yes" : "back.no",
|
|
)
|
|
: fieldValue}
|
|
</p>
|
|
);
|
|
} else {
|
|
cellContent = (
|
|
<p className={placeholderClasses}>{tableNotKnownTrans}</p>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="grid grid-cols-[1fr_1fr_auto] items-center w-full gap-4">
|
|
<p className={cellClasses}>{field.label}</p>
|
|
{cellContent}
|
|
{!currentHasChildren && <div className="w-[16px]" />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<AccordionItem
|
|
key={accordionKey}
|
|
value={accordionKey}
|
|
className="border-none"
|
|
>
|
|
{hasChildren ? (
|
|
<AccordionTrigger
|
|
className={cn(
|
|
"gap-0 px-4",
|
|
{ "rounded-none border-b mb-2": hasBorders },
|
|
{ "py-2": !hasBorders },
|
|
)}
|
|
>
|
|
{rowContent(hasChildren)}
|
|
</AccordionTrigger>
|
|
) : (
|
|
<div className="px-4 py-2">{rowContent()}</div>
|
|
)}
|
|
|
|
{hasChildren &&
|
|
Array.isArray(
|
|
currentValue[field.key as keyof typeof currentValue],
|
|
) &&
|
|
Object.values(
|
|
currentValue[field.key as keyof typeof currentValue],
|
|
).length > 0 && (
|
|
<AccordionContent className="px-4">
|
|
<div className="space-y-1">
|
|
{Object.values(
|
|
currentValue[
|
|
field.key as keyof typeof currentValue
|
|
] as ChildItem[],
|
|
).map((childItem: ChildItem) => (
|
|
<div
|
|
key={String(childItem.id)}
|
|
className="border rounded-md"
|
|
>
|
|
{RenderRows(
|
|
childItem,
|
|
field.children!,
|
|
false,
|
|
`${accordionKey}-${childItem.id}`,
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</AccordionContent>
|
|
)}
|
|
</AccordionItem>
|
|
);
|
|
});
|
|
};
|
|
|
|
type DynamicPageDetailsProps = {
|
|
value: string | object;
|
|
config: ConfigField[];
|
|
};
|
|
|
|
export default function DynamicPageDetails({
|
|
value,
|
|
config,
|
|
}: DynamicPageDetailsProps) {
|
|
const transLabel = str(useTrans("validation.custom.label"))
|
|
.ucFirst()
|
|
.value();
|
|
const transValue = str(useTrans("validation.custom.value"))
|
|
.ucFirst()
|
|
.value();
|
|
|
|
return (
|
|
<Accordion type="multiple" className="w-full divide-y">
|
|
{/* HEADER */}
|
|
<div className="grid grid-cols-[1fr_1fr_auto] text-sm font-medium border-b gap-4 px-4 py-2">
|
|
<div>{transLabel}</div>
|
|
<div>{transValue}</div>
|
|
<div className="w-[16px]" />
|
|
</div>
|
|
|
|
{/* ROWS */}
|
|
{RenderRows(value, config, true)}
|
|
</Accordion>
|
|
);
|
|
}
|