Files
papercrate/frontend/src/hooks/documents/useDocuments.ts
T
2025-11-13 01:07:55 +01:00

108 lines
2.9 KiB
TypeScript

import { Dispatch, SetStateAction, useCallback, useState } from 'react';
interface DocumentLike {
id?: string | number;
[key: string]: unknown;
}
interface FolderContentsEntry {
documents?: DocumentLike[];
[key: string]: unknown;
}
interface UseDocumentsOptions {
setSearchResults: Dispatch<SetStateAction<DocumentLike[] | null | undefined>>;
setFolderContents: Dispatch<SetStateAction<Map<string, FolderContentsEntry>>>;
}
const useDocuments = ({ setSearchResults, setFolderContents }: UseDocumentsOptions) => {
const [documents, setDocuments] = useState<DocumentLike[]>([]);
const mapDocumentCaches = useCallback(
(mapper: (doc: DocumentLike) => DocumentLike | undefined) => {
if (typeof mapper !== 'function') {
return;
}
const applyToList = (list?: DocumentLike[] | null) => {
let changed = false;
const safeList = Array.isArray(list) ? list : [];
const next = safeList.map((doc) => {
const updated = mapper(doc);
if (updated === undefined || updated === doc) {
return doc;
}
changed = true;
return updated;
});
return changed ? next : safeList;
};
setDocuments((prev) => applyToList(prev));
setSearchResults((prev) => {
if (!Array.isArray(prev)) {
return prev;
}
return applyToList(prev);
});
setFolderContents((prev) => {
if (!prev.size) {
return prev;
}
let changed = false;
const next = new Map();
prev.forEach((contents, key) => {
const docs = Array.isArray(contents?.documents) ? contents.documents : null;
if (!docs || docs.length === 0) {
next.set(key, contents);
return;
}
let docsChanged = false;
const updatedDocs = docs.map((doc) => {
const updated = mapper(doc);
if (updated === undefined || updated === doc) {
return doc;
}
docsChanged = true;
return updated;
});
if (docsChanged) {
changed = true;
next.set(key, { ...contents, documents: updatedDocs });
} else {
next.set(key, contents);
}
});
return changed ? next : prev;
});
},
[setFolderContents, setSearchResults],
);
const updateDocumentCaches = useCallback(
(documentId, updater) => {
if (!documentId || typeof updater !== 'function') {
return;
}
mapDocumentCaches((doc) => {
if (!doc || doc.id !== documentId) {
return doc;
}
const updated = updater(doc);
return updated === undefined ? doc : updated;
});
},
[mapDocumentCaches],
);
return {
documents,
setDocuments,
mapDocumentCaches,
updateDocumentCaches,
};
};
export default useDocuments;