refactor: Decompose document and folder views into modular components and hooks, replacing monolithic list/grid implementations.

This commit is contained in:
2025-11-26 01:50:53 +01:00
parent 342714528a
commit 0a4a3ae35c
20 changed files with 1074 additions and 917 deletions
@@ -0,0 +1,143 @@
import React from 'react';
import { FolderIcon } from '../../ui/icons';
import { formatDate } from '../../utils/date';
import DocumentThumbnailImage from '../DocumentThumbnailImage';
import { resolveCorrespondents } from '../correspondents';
import type { DocumentsListEntry } from '../../types/documents';
import type { DocumentsViewProps } from '../panel/DocumentsPanel';
import type { DocumentViewLogic } from '../hooks/useDocumentViewLogic';
import EditableEntryTitle from './EditableEntryTitle';
import EntryCorrespondents from './EntryCorrespondents';
import EntryTags from './EntryTags';
import FolderEntry from './FolderEntry';
import DocumentEntry from './DocumentEntry';
interface DocumentsListRowProps extends DocumentsViewProps {
entry: DocumentsListEntry;
viewLogic: DocumentViewLogic;
}
const DocumentsListRow: React.FC<DocumentsListRowProps> = (props) => {
const { entry } = props;
if (entry.type === 'folder') {
const folder = entry.folder;
if (!folder) return null;
return (
<FolderEntry
{...props}
folder={folder}
component="tr"
className="folder"
>
{(logic) => (
<>
<td className="thumb-cell">
<div className="thumb-icon">
<FolderIcon className="thumb-icon__image" size={32} />
</div>
</td>
<td className="doc-list__name">
<div className="doc-list__name-content">
<span className="doc-name__title">
<span className="doc-name__primary">
<EditableEntryTitle
isEditing={logic.isFolderEditing}
draftValue={logic.folderDraftValue}
onChange={logic.handlers.onRenameChange}
onSubmit={logic.handlers.onRenameSubmit}
onCancel={logic.handlers.onRenameCancel}
isSaving={logic.isFolderSaving}
canSubmit={logic.canSubmitFolder}
inputRef={logic.attachFolderInputRef}
allowInlineEdit={logic.allowInlineFolderEdit}
onBeginEditing={logic.handlers.onRenameBegin}
className="doc-name__primary-text"
>
{folder.name}
</EditableEntryTitle>
</span>
</span>
</div>
</td>
<td></td>
<td></td>
</>
)}
</FolderEntry>
);
}
const doc = entry.document;
if (!doc) return null;
const correspondents = resolveCorrespondents(doc);
const issuedLabel = formatDate(doc.issued_at);
const addedLabel = formatDate(doc.created_at || doc.uploaded_at);
return (
<DocumentEntry
{...props}
doc={doc}
component="tr"
className="document"
>
{(logic) => (
<>
<td className="thumb-cell">
<DocumentThumbnailImage
document={doc}
ensureAssetUrl={props.ensureAssetUrl}
getDocumentAsset={props.getDocumentAsset}
alt={`Thumbnail for ${doc.title}`}
scrollRootRef={props.scrollRef}
/>
</td>
<td className="doc-list__name">
<div className="doc-name">
<div className="doc-list__name-content">
<span className="doc-name__title">
<EntryCorrespondents
correspondents={correspondents}
activeCorrespondentIdSet={props.activeCorrespondentIdSet}
onCorrespondentClick={props.onCorrespondentClick}
/>
<span className="doc-name__primary">
<EditableEntryTitle
isEditing={logic.isEditingDoc}
draftValue={logic.documentDraftValue}
onChange={logic.handlers.onRenameChange}
onSubmit={logic.handlers.onRenameSubmit}
onCancel={logic.handlers.onRenameCancel}
isSaving={logic.isDocumentSaving}
canSubmit={logic.canSubmitDocument}
inputRef={logic.attachDocumentInputRef}
allowInlineEdit={logic.allowInlineDocumentEdit}
onBeginEditing={logic.handlers.onRenameBegin}
className="doc-name__primary-text"
>
{doc.title}
</EditableEntryTitle>
</span>
</span>
</div>
<div className="doc-name__tags">
<EntryTags
tags={doc.tags || []}
tagLookupById={props.tagLookupById}
onTagClick={props.onTagClick}
docId={doc.id}
/>
</div>
</div>
</td>
<td>{issuedLabel}</td>
<td>{addedLabel}</td>
</>
)}
</DocumentEntry>
);
};
export default DocumentsListRow;