used detailview api instead of audit

This commit is contained in:
suryacp23 2026-07-17 17:21:47 +05:30
parent edddb1b696
commit 3492cdbf9e
2 changed files with 18 additions and 45 deletions

View File

@ -6,7 +6,7 @@
<link rel="icon" href="/favicon.svg" type="image/svg+xml" /> <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="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#0B1B3B" /> <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-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Krishna Sales" /> <meta name="apple-mobile-web-app-title" content="Krishna Sales" />
<link rel="apple-touch-icon" href="/apple-touch-icon-180x180.png" /> <link rel="apple-touch-icon" href="/apple-touch-icon-180x180.png" />

View File

@ -2,8 +2,7 @@ import { useEffect, useState } from 'react';
import { cn } from '../../lib/cn'; import { cn } from '../../lib/cn';
import { formatValue } from '../../lib/format'; import { formatValue } from '../../lib/format';
import type { ZinoClient } from '../../api/client'; import type { ZinoClient } from '../../api/client';
import type { AuditEntry } from '../../api/types'; import { APP_ID } from '../../api/config';
import { WORKFLOWS, APP_ID } from '../../api/config';
import { Card } from '../reusable/Card'; import { Card } from '../reusable/Card';
import { Spinner } from '../reusable/Spinner'; import { Spinner } from '../reusable/Spinner';
import { EmptyState } from '../reusable/EmptyState'; import { EmptyState } from '../reusable/EmptyState';
@ -11,7 +10,7 @@ import { EmptyState } from '../reusable/EmptyState';
export interface DetailViewProps { export interface DetailViewProps {
/** Workflow-bound client (see api/clients.ts). */ /** Workflow-bound client (see api/clients.ts). */
client: ZinoClient; client: ZinoClient;
/** detailview template uid (deprecated, using audit endpoint now). */ /** detailview template uid. */
dvUid?: string; dvUid?: string;
/** Instance to render. */ /** Instance to render. */
instanceId: number | string; instanceId: number | string;
@ -23,29 +22,13 @@ export interface DetailViewProps {
columns?: 1 | 2 | 3; 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 * Generic Zino detail view. Fetches `GET /app/{id}/view/detailview/{dvUid}` and
* renders the audit trail as a labeled definition grid. * renders the data as a labeled definition grid.
*/ */
export function DetailView({ client, instanceId, title, columns = 2 }: DetailViewProps) { export function DetailView({ client, dvUid, instanceId, title, fields, columns = 2 }: DetailViewProps) {
const [entries, setEntries] = useState<AuditEntry[]>([]); const [data, setData] = useState<Record<string, unknown> | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
@ -55,9 +38,10 @@ export function DetailView({ client, instanceId, title, columns = 2 }: DetailVie
setLoading(true); setLoading(true);
setError(null); setError(null);
try { 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) { if (live) {
setEntries(r || []); setData(r.data || {});
} }
} catch (e) { } catch (e) {
if (live) setError((e as { message?: string })?.message ?? 'Failed to load'); 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 () => { return () => {
live = false; 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]; 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 ( return (
<Card title={title}> <Card title={title}>
<EmptyState title="No history found" /> <EmptyState title="No details found" />
</Card> </Card>
); );
} }
return ( return (
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
{entries.map((entry, i) => { <Card title={title || 'Details'}>
const actName = getActivityName(entry.activity_id); <dl className={cn('grid gap-x-6 gap-y-4', gridCols)}>
const headerTitle = actName || (i === 0 && title ? title : 'Update'); {Object.entries(data).map(([key, value]) => {
const updatedAt = new Date(entry.created_at).toLocaleString(); if (fields && !fields.includes(key)) return null;
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]) => {
const isGridArray = const isGridArray =
Array.isArray(value) && Array.isArray(value) &&
value.length > 0 && value.length > 0 &&
@ -213,9 +188,7 @@ export function DetailView({ client, instanceId, title, columns = 2 }: DetailVie
); );
})} })}
</dl> </dl>
</Card> </Card>
);
})}
</div> </div>
); );
} }