import { type ComponentPropsWithRef, type ReactNode, useMemo } from 'react';
import { PiCalendarBlank } from 'react-icons/pi';
import { type AnyResource, getTitleOfResource } from '@wener/common/resource';
import { DataViewLayout } from './DataViewLayout';
type IAnyResource = AnyResource & {
createdBy?: AnyResource;
updatedBy?: AnyResource;
};
/**
* Get description from resource
*/
export function getDescriptionOfResource(res?: any): string | undefined {
if (res && typeof res === 'object') {
return res.description || res.remark;
}
return undefined;
}
/**
* Format resource title with code
*/
export function formatResourceTitle(data: IAnyResource): ReactNode {
const { code } = data;
let primary: ReactNode = data.title || data.fullName;
let sec = data.displayName;
primary ||= sec;
if (sec === primary) {
sec = undefined;
}
return (
{code && {code}}
{Boolean(primary) && {primary}}
{sec && ({sec})}
);
}
/**
* Format resource meta info (dates, owner, etc.)
*/
export function formatResourceMeta(data: IAnyResource): ReactNode {
const { createdAt, updatedAt, createdBy, updatedBy } = data;
const parts: ReactNode[] = [];
// Created by
if (createdBy) {
const creatorName = getTitleOfResource(createdBy);
if (creatorName) {
parts.push(
创建者: {creatorName}
,
);
}
}
// Updated by
if (updatedBy && updatedBy.id !== createdBy?.id) {
const updaterName = getTitleOfResource(updatedBy);
if (updaterName) {
parts.push(
更新者: {updaterName}
,
);
}
}
// Dates
if (createdAt || updatedAt) {
const dates: ReactNode[] = [];
if (updatedAt) {
dates.push(
{typeof updatedAt === 'string'
? new Date(updatedAt).toLocaleDateString()
: updatedAt.toLocaleDateString()}
,
);
}
if (createdAt && createdAt !== updatedAt) {
dates.push(
(创建:{' '}
{typeof createdAt === 'string'
? new Date(createdAt).toLocaleDateString()
: createdAt.toLocaleDateString()}
)
,
);
}
parts.push(
{dates}
,
);
}
return parts.length > 0 ? <>{parts.map((p, i) => (i > 0 ? [' • ', p] : p))}> : null;
}
export type ResourceListItemProps = Omit<
ComponentPropsWithRef,
'data' | 'title' | 'description' | 'meta'
> & {
data: AnyResource;
showCode?: boolean; // Whether to show resource code in title
showMeta?: boolean; // Whether to show meta info (dates, creator, etc.)
customTitle?: (data: AnyResource) => ReactNode;
customDescription?: (data: AnyResource) => ReactNode;
customMeta?: (data: AnyResource) => ReactNode;
};
export const ResourceListItem = ({
data,
showCode = true,
showMeta = true,
customTitle,
customDescription,
customMeta,
...props
}: ResourceListItemProps) => {
const title = useMemo(() => {
if (customTitle) return customTitle(data);
return showCode ? formatResourceTitle(data) : getTitleOfResource(data);
}, [data, showCode, customTitle]);
const description = useMemo(() => {
if (customDescription) return customDescription(data);
return getDescriptionOfResource(data);
}, [data, customDescription]);
const meta = useMemo(() => {
if (customMeta) return customMeta(data);
if (!showMeta) return null;
return formatResourceMeta(data);
}, [data, showMeta, customMeta]);
return ;
};