typescript
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import { formatFileSize } from '../utils/format';
|
||||
import { formatDateTime as defaultFormatDateTime } from '../utils/date';
|
||||
|
||||
interface DocumentMetadata {
|
||||
page_count?: number | string | null;
|
||||
}
|
||||
|
||||
interface DocumentVersion {
|
||||
size_bytes?: number | string | null;
|
||||
metadata?: DocumentMetadata | null;
|
||||
}
|
||||
|
||||
interface TagEntry {
|
||||
label?: string | null;
|
||||
}
|
||||
|
||||
interface CorrespondentEntry {
|
||||
name?: string | null;
|
||||
}
|
||||
|
||||
export interface SummaryDocument {
|
||||
title?: string | null;
|
||||
original_name?: string | null;
|
||||
content_type?: string | null;
|
||||
current_version?: DocumentVersion | null;
|
||||
created_at?: string | null;
|
||||
updated_at?: string | null;
|
||||
issued_at?: string | null;
|
||||
folder_path?: string | null;
|
||||
tags?: TagEntry[] | null;
|
||||
correspondents?: CorrespondentEntry[] | null;
|
||||
}
|
||||
|
||||
interface DescribeSummaryOptions {
|
||||
formatDateTime?: typeof defaultFormatDateTime;
|
||||
}
|
||||
|
||||
export interface DocumentSummaryRow {
|
||||
key: string;
|
||||
label: string;
|
||||
value: string | null | undefined;
|
||||
}
|
||||
|
||||
export interface DocumentSummary {
|
||||
title: string | undefined;
|
||||
originalName: string | null | undefined;
|
||||
mimeTypeLabel: string;
|
||||
sizeLabel: string;
|
||||
createdAtLabel: string;
|
||||
issuedLabel: string;
|
||||
updatedAtLabel: string;
|
||||
pageCount: number | null;
|
||||
pageCountLabel: string;
|
||||
folderLabel: string | null | undefined;
|
||||
tags: TagEntry[];
|
||||
correspondents: CorrespondentEntry[];
|
||||
tagsSummary: string;
|
||||
correspondentsSummary: string;
|
||||
summaryRows: DocumentSummaryRow[];
|
||||
}
|
||||
|
||||
const coercePageCount = (metadata: DocumentMetadata | null | undefined): number | null => {
|
||||
const raw = metadata?.page_count;
|
||||
if (typeof raw === 'number') {
|
||||
return Number.isFinite(raw) && raw >= 0 ? raw : null;
|
||||
}
|
||||
if (raw != null && raw !== '') {
|
||||
const parsed = Number.parseInt(String(raw), 10);
|
||||
if (Number.isFinite(parsed) && parsed >= 0) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const sanitizeArray = <T>(entries: (T | null | undefined)[] | null | undefined): T[] =>
|
||||
Array.isArray(entries) ? entries.filter(Boolean) as T[] : [];
|
||||
|
||||
export const describeDocumentSummary = (document?: SummaryDocument | null, options: DescribeSummaryOptions = {}): DocumentSummary => {
|
||||
const {
|
||||
formatDateTime = defaultFormatDateTime,
|
||||
} = options;
|
||||
|
||||
if (!document) {
|
||||
return {
|
||||
title: '',
|
||||
originalName: '',
|
||||
mimeTypeLabel: '—',
|
||||
sizeLabel: '—',
|
||||
createdAtLabel: '—',
|
||||
issuedLabel: '—',
|
||||
updatedAtLabel: '—',
|
||||
pageCount: null,
|
||||
pageCountLabel: '—',
|
||||
folderLabel: null,
|
||||
tags: [],
|
||||
correspondents: [],
|
||||
tagsSummary: '—',
|
||||
correspondentsSummary: '—',
|
||||
summaryRows: [],
|
||||
};
|
||||
}
|
||||
|
||||
const originalName = document.original_name;
|
||||
const mimeTypeLabel = document.content_type || 'Unknown';
|
||||
|
||||
const sizeBytes = Number(document.current_version?.size_bytes);
|
||||
const sizeLabel = Number.isFinite(sizeBytes) && sizeBytes > 0 ? formatFileSize(sizeBytes) : '—';
|
||||
|
||||
const metadata = document.current_version?.metadata || null;
|
||||
const pageCount = coercePageCount(metadata);
|
||||
const pageCountLabel = Number.isFinite(pageCount) ? String(pageCount) : '—';
|
||||
|
||||
const createdAtLabel = formatDateTime(document.created_at);
|
||||
const issuedLabel = formatDateTime(document.issued_at);
|
||||
const updatedAtLabel = formatDateTime(document.updated_at);
|
||||
|
||||
const folderLabel = document.folder_path;
|
||||
|
||||
const tags = sanitizeArray<TagEntry>(document.tags);
|
||||
const correspondents = sanitizeArray<CorrespondentEntry>(document.correspondents);
|
||||
|
||||
const tagLabels = tags.map((tag) => tag.label).filter(Boolean) as string[];
|
||||
const correspondentLabels = correspondents.map((entry) => entry.name).filter(Boolean) as string[];
|
||||
|
||||
const tagsSummary = tagLabels.length ? tagLabels.join(', ') : '—';
|
||||
const correspondentsSummary = correspondentLabels.length
|
||||
? correspondentLabels.join(', ')
|
||||
: '—';
|
||||
|
||||
const summaryRows: DocumentSummaryRow[] = [
|
||||
{ key: 'created', label: 'Created', value: createdAtLabel },
|
||||
{ key: 'size', label: 'Size', value: sizeLabel },
|
||||
{ key: 'type', label: 'Type', value: mimeTypeLabel },
|
||||
{ key: 'issued', label: 'Issued', value: issuedLabel },
|
||||
{ key: 'pages', label: 'Pages', value: pageCountLabel },
|
||||
{ key: 'updated', label: 'Updated', value: updatedAtLabel },
|
||||
{ key: 'folder', label: 'Folder', value: folderLabel },
|
||||
{ key: 'tags', label: 'Tags', value: tagsSummary },
|
||||
{ key: 'correspondents', label: 'Correspondents', value: correspondentsSummary },
|
||||
];
|
||||
|
||||
return {
|
||||
title: document.title,
|
||||
originalName,
|
||||
mimeTypeLabel,
|
||||
sizeLabel,
|
||||
createdAtLabel,
|
||||
issuedLabel,
|
||||
updatedAtLabel,
|
||||
pageCount,
|
||||
pageCountLabel,
|
||||
folderLabel,
|
||||
tags,
|
||||
correspondents,
|
||||
tagsSummary,
|
||||
correspondentsSummary,
|
||||
summaryRows,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user