Files
papercrate/frontend/src/documents/hooks/useBulkDocumentActions.js
T
2025-11-10 14:46:34 +01:00

207 lines
5.8 KiB
JavaScript

import { useCallback } from 'react';
const useBulkDocumentActions = ({
api,
resolveTargetDocumentIds,
correspondentLookupByName,
handleCorrespondentCreate,
refreshCurrentFolder,
setStatusMessage,
selectedDocumentIds,
selectedFolderIds,
handleDocumentsDelete,
handleFolderDelete,
clearDocumentSelection,
setLoading,
}) => {
const handleBulkCorrespondentAdd = useCallback(
async ({ name, input, documentIds }) => {
const trimmed = typeof name === 'string' ? name.trim() : '';
if (!trimmed) {
setStatusMessage('Correspondent name is required.', 'error');
return;
}
const targets = resolveTargetDocumentIds(documentIds);
if (!targets.length) {
setStatusMessage('Select documents before assigning correspondents.', 'error');
return;
}
let target = correspondentLookupByName.get(trimmed.toLowerCase()) || null;
if (!target) {
try {
target = await handleCorrespondentCreate({ name: trimmed });
} catch {
return;
}
}
if (!target?.id) {
setStatusMessage('Unable to resolve correspondent.', 'error');
return;
}
const response = await api.post('/documents/bulk/correspondents', {
document_ids: targets,
assignments: [
{
correspondent_id: target.id,
},
],
action: 'add',
});
const { assigned = 0, removed = 0 } = response.data || {};
await refreshCurrentFolder();
const assignedSuffix = assigned === 1 ? '' : 's';
if (removed > 0) {
const removedSuffix = removed === 1 ? '' : 's';
setStatusMessage(
`Correspondent assigned (${assigned}) and replaced ${removed} link${removedSuffix}.`,
'success',
);
} else {
setStatusMessage(
`Correspondent assigned to ${assigned} document${assignedSuffix}.`,
'success',
);
}
if (input) {
input.value = '';
}
},
[
api,
correspondentLookupByName,
handleCorrespondentCreate,
refreshCurrentFolder,
resolveTargetDocumentIds,
setStatusMessage,
],
);
const handleBulkCorrespondentRemove = useCallback(
async ({ assignments = [], documentIds }) => {
if (!assignments.length) {
setStatusMessage('Select a correspondent to remove.', 'error');
return;
}
const targets = resolveTargetDocumentIds(documentIds);
if (!targets.length) {
setStatusMessage('Select documents before removing correspondents.', 'error');
return;
}
const normalizedAssignments = assignments.map((entry) => ({
correspondent_id: entry.correspondent_id,
}));
const response = await api.post('/documents/bulk/correspondents', {
document_ids: targets,
assignments: normalizedAssignments,
action: 'remove',
});
const { assigned = 0, removed = 0 } = response.data || {};
await refreshCurrentFolder();
if (removed > 0) {
const removedSuffix = removed === 1 ? '' : 's';
setStatusMessage(
`Correspondent removed from ${removed} link${removedSuffix}.`,
'success',
);
} else if (assigned > 0) {
const assignedSuffix = assigned === 1 ? '' : 's';
setStatusMessage(`Correspondent updated ${assigned} link${assignedSuffix}.`, 'info');
} else {
setStatusMessage('No correspondents changed.', 'info');
}
},
[api, refreshCurrentFolder, resolveTargetDocumentIds, setStatusMessage],
);
const handleDeleteSelection = useCallback(async () => {
const docIds = Array.isArray(selectedDocumentIds) ? selectedDocumentIds : [];
const folderIds = Array.isArray(selectedFolderIds) ? selectedFolderIds : [];
if (docIds.length === 0 && folderIds.length === 0) {
return;
}
const parts = [];
if (docIds.length) {
parts.push(`${docIds.length} document${docIds.length === 1 ? '' : 's'}`);
}
if (folderIds.length) {
parts.push(`${folderIds.length} folder${folderIds.length === 1 ? '' : 's'}`);
}
const descriptor = parts.join(' and ');
const confirmation = parts.length === 1
? `Delete ${descriptor}? Folders must be empty before deletion. You can restore documents later from trash.`
: `Delete ${descriptor}? Folders must be empty before deletion. You can restore documents later from trash.`;
if (!window.confirm(confirmation)) {
return;
}
setLoading(true);
let docsOk = true;
let foldersOk = true;
try {
if (docIds.length) {
docsOk = await handleDocumentsDelete(docIds, { showMessage: false, manageLoading: false });
}
if (folderIds.length) {
for (const folderId of folderIds) {
const success = await handleFolderDelete(folderId, { showMessage: false, manageLoading: false });
if (!success) {
foldersOk = false;
}
}
}
} finally {
setLoading(false);
}
if (!docsOk || !foldersOk) {
setStatusMessage('Some items could not be deleted. Ensure folders are empty before deletion.', 'error');
return;
}
clearDocumentSelection();
const successParts = [];
if (docIds.length) {
successParts.push(docIds.length === 1 ? 'Document deleted.' : 'Documents deleted.');
}
if (folderIds.length) {
successParts.push(folderIds.length === 1 ? 'Folder deleted.' : 'Folders deleted.');
}
setStatusMessage(successParts.join(' '), 'success');
}, [
clearDocumentSelection,
handleDocumentsDelete,
handleFolderDelete,
selectedDocumentIds,
selectedFolderIds,
setLoading,
setStatusMessage,
]);
return {
handleBulkCorrespondentAdd,
handleBulkCorrespondentRemove,
handleDeleteSelection,
};
};
export default useBulkDocumentActions;