used detailview api instead of audit
This commit is contained in:
parent
edddb1b696
commit
3492cdbf9e
@ -6,7 +6,7 @@
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta name="theme-color" content="#0B1B3B" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="apple-mobile-web-app-title" content="Krishna Sales" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon-180x180.png" />
|
||||
|
||||
@ -2,8 +2,7 @@ import { useEffect, useState } from 'react';
|
||||
import { cn } from '../../lib/cn';
|
||||
import { formatValue } from '../../lib/format';
|
||||
import type { ZinoClient } from '../../api/client';
|
||||
import type { AuditEntry } from '../../api/types';
|
||||
import { WORKFLOWS, APP_ID } from '../../api/config';
|
||||
import { APP_ID } from '../../api/config';
|
||||
import { Card } from '../reusable/Card';
|
||||
import { Spinner } from '../reusable/Spinner';
|
||||
import { EmptyState } from '../reusable/EmptyState';
|
||||
@ -11,7 +10,7 @@ import { EmptyState } from '../reusable/EmptyState';
|
||||
export interface DetailViewProps {
|
||||
/** Workflow-bound client (see api/clients.ts). */
|
||||
client: ZinoClient;
|
||||
/** detailview template uid (deprecated, using audit endpoint now). */
|
||||
/** detailview template uid. */
|
||||
dvUid?: string;
|
||||
/** Instance to render. */
|
||||
instanceId: number | string;
|
||||
@ -23,29 +22,13 @@ export interface DetailViewProps {
|
||||
columns?: 1 | 2 | 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to resolve a human-readable activity name from its UID.
|
||||
*/
|
||||
function getActivityName(uid: string): string | undefined {
|
||||
for (const wf of Object.values(WORKFLOWS)) {
|
||||
for (const [actName, actDef] of Object.entries(wf.activities)) {
|
||||
if (actDef.uid === uid) {
|
||||
return actName
|
||||
.split('_')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||
.join(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic Zino detail view. Fetches `GET /app/{id}/view/audit` and
|
||||
* renders the audit trail as a labeled definition grid.
|
||||
* Generic Zino detail view. Fetches `GET /app/{id}/view/detailview/{dvUid}` and
|
||||
* renders the data as a labeled definition grid.
|
||||
*/
|
||||
export function DetailView({ client, instanceId, title, columns = 2 }: DetailViewProps) {
|
||||
const [entries, setEntries] = useState<AuditEntry[]>([]);
|
||||
export function DetailView({ client, dvUid, instanceId, title, fields, columns = 2 }: DetailViewProps) {
|
||||
const [data, setData] = useState<Record<string, unknown> | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@ -55,9 +38,10 @@ export function DetailView({ client, instanceId, title, columns = 2 }: DetailVie
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const r = await client.audit(instanceId);
|
||||
if (!dvUid) throw new Error("dvUid is required to fetch detail view data.");
|
||||
const r = await client.detailView(dvUid, instanceId);
|
||||
if (live) {
|
||||
setEntries(r || []);
|
||||
setData(r.data || {});
|
||||
}
|
||||
} catch (e) {
|
||||
if (live) setError((e as { message?: string })?.message ?? 'Failed to load');
|
||||
@ -69,7 +53,7 @@ export function DetailView({ client, instanceId, title, columns = 2 }: DetailVie
|
||||
return () => {
|
||||
live = false;
|
||||
};
|
||||
}, [client, instanceId]);
|
||||
}, [client, dvUid, instanceId]);
|
||||
|
||||
const gridCols = { 1: 'grid-cols-1', 2: 'grid-cols-1 sm:grid-cols-2', 3: 'grid-cols-1 sm:grid-cols-3' }[columns];
|
||||
|
||||
@ -91,29 +75,20 @@ export function DetailView({ client, instanceId, title, columns = 2 }: DetailVie
|
||||
);
|
||||
}
|
||||
|
||||
if (entries.length === 0) {
|
||||
if (!data || Object.keys(data).length === 0) {
|
||||
return (
|
||||
<Card title={title}>
|
||||
<EmptyState title="No history found" />
|
||||
<EmptyState title="No details found" />
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{entries.map((entry, i) => {
|
||||
const actName = getActivityName(entry.activity_id);
|
||||
const headerTitle = actName || (i === 0 && title ? title : 'Update');
|
||||
const updatedAt = new Date(entry.created_at).toLocaleString();
|
||||
|
||||
return (
|
||||
<Card
|
||||
key={entry.id}
|
||||
title={headerTitle}
|
||||
action={<span className="text-xs font-medium text-faint">{updatedAt}</span>}
|
||||
>
|
||||
<dl className={cn('grid gap-x-6 gap-y-4', gridCols)}>
|
||||
{Object.entries(entry.data).map(([key, value]) => {
|
||||
<Card title={title || 'Details'}>
|
||||
<dl className={cn('grid gap-x-6 gap-y-4', gridCols)}>
|
||||
{Object.entries(data).map(([key, value]) => {
|
||||
if (fields && !fields.includes(key)) return null;
|
||||
const isGridArray =
|
||||
Array.isArray(value) &&
|
||||
value.length > 0 &&
|
||||
@ -213,9 +188,7 @@ export function DetailView({ client, instanceId, title, columns = 2 }: DetailVie
|
||||
);
|
||||
})}
|
||||
</dl>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user