tech_mahindra/src/components/ScreenRenderer.tsx

103 lines
3.5 KiB
TypeScript

import { useState, ReactNode } from "react";
import { Plus } from "lucide-react";
import type { LayoutElement } from "../api/viewService";
import RecordViewTable from "./RecordViewTable";
import DetailViewPanel from "./DetailViewPanel";
import FormModal from "./FormModal";
interface Props {
layout: LayoutElement[];
instanceId?: string;
onRefresh?: () => void;
onRowClick?: (instanceId: string) => void;
}
interface AnyNode {
type?: string;
style?: Record<string, string>;
config?: Record<string, any>;
children?: AnyNode[];
}
function flatten(nodes: AnyNode[] | undefined): AnyNode[] {
if (!nodes) return [];
const out: AnyNode[] = [];
for (const n of nodes) {
if (n.config && (n.config.type || n.config.job_template)) out.push(n);
if (n.children?.length) out.push(...flatten(n.children));
}
return out;
}
export default function ScreenRenderer({ layout, instanceId, onRefresh, onRowClick }: Props) {
const [formModal, setFormModal] = useState<{ activityId: string; instanceId?: string; title?: string } | null>(null);
const buttons: ReactNode[] = [];
const elements: { type: "rv" | "dv"; viewId: number | string; style?: Record<string, string> }[] = [];
for (const node of flatten(layout as AnyNode[])) {
const cfg = node.config!;
if (cfg.type === "button" || cfg.job_template) {
const aid =
cfg.params?.activity_uid_init ||
cfg.params?.activity_id_init ||
cfg.params?.activity_uid ||
cfg.params?.activity_id;
if (!aid) continue;
const label = (cfg.name || "").replace(/^\+\s*/, "");
buttons.push(
<button
key={aid}
onClick={() => setFormModal({ activityId: aid, instanceId: cfg.job_template === "perform_activity" ? instanceId : undefined, title: label })}
className="h-8 px-3.5 text-[12px] font-semibold text-white rounded-xl inline-flex items-center gap-1.5 transition-all hover:scale-[1.02] active:scale-[0.98] mh-glow"
style={{ background: "linear-gradient(135deg, #C8102E, #E84258)" }}
>
<Plus size={13} strokeWidth={2.5} />{label}
</button>
);
} else if (cfg.type === "recordsview") {
const id = cfg.view_uuid || cfg.view_id;
elements.push({ type: "rv", viewId: id, style: node.style });
} else if (cfg.type === "detailsview") {
const id = cfg.view_uuid || cfg.view_id;
elements.push({ type: "dv", viewId: id, style: node.style });
}
}
return (
<>
<div className="space-y-4">
{elements.map((el, i) => {
if (el.type === "rv") {
return (
<div key={i} style={el.style}>
<RecordViewTable
viewId={el.viewId}
onRowClick={onRowClick}
toolbarAction={buttons.length > 0 ? <div className="flex items-center gap-2">{buttons}</div> : undefined}
/>
</div>
);
}
if (el.type === "dv") {
return <div key={i} style={el.style}><DetailViewPanel viewId={el.viewId} instanceId={instanceId || ""} /></div>;
}
return null;
})}
{elements.length === 0 && buttons.length > 0 && (
<div className="flex items-center gap-2">{buttons}</div>
)}
</div>
{formModal && (
<FormModal
activityId={formModal.activityId}
instanceId={formModal.instanceId}
title={formModal.title}
onClose={() => setFormModal(null)}
onSuccess={() => { setFormModal(null); onRefresh?.(); }}
/>
)}
</>
);
}