@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
219 lines • 9.81 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useCollectionsActions = useCollectionsActions;
const react_1 = require("react");
const hooks_1 = require("../../store/hooks");
const collectionsSlice_1 = require("../../store/slices/collectionsSlice");
const collectionsApi_1 = require("../../store/api/collectionsApi");
const handleError_1 = require("../../utils/handleError");
/**
* Redux-powered hook that provides all collection actions
* This replaces the individual hooks and provides a centralized way to manage collections
*/
function useCollectionsActions() {
const dispatch = (0, hooks_1.useReplykeDispatch)();
// Use a ref so removeFromCollection can read the latest entities without being in deps
const entitiesByCollectionId = (0, hooks_1.useReplykeSelector)((state) => state.replyke.collections.entitiesByCollectionId);
const entitiesByCollectionIdRef = (0, react_1.useRef)(entitiesByCollectionId);
entitiesByCollectionIdRef.current = entitiesByCollectionId;
// RTK Query hooks
const [fetchRootCollectionQuery] = (0, collectionsApi_1.useLazyFetchRootCollectionQuery)();
const [fetchSubCollectionsQuery] = (0, collectionsApi_1.useLazyFetchSubCollectionsQuery)();
const [createCollectionMutation] = (0, collectionsApi_1.useCreateCollectionMutation)();
const [updateCollectionMutation] = (0, collectionsApi_1.useUpdateCollectionMutation)();
const [deleteCollectionMutation] = (0, collectionsApi_1.useDeleteCollectionMutation)();
const [addToCollectionMutation] = (0, collectionsApi_1.useAddToCollectionMutation)();
const [removeFromCollectionMutation] = (0, collectionsApi_1.useRemoveFromCollectionMutation)();
// Navigation actions
const openCollectionAction = (0, react_1.useCallback)((collection) => {
dispatch((0, collectionsSlice_1.openCollection)(collection));
}, [dispatch]);
const goBackAction = (0, react_1.useCallback)(() => {
dispatch((0, collectionsSlice_1.goBack)());
}, [dispatch]);
const goToRootAction = (0, react_1.useCallback)(() => {
dispatch((0, collectionsSlice_1.goToRoot)());
}, [dispatch]);
// Fetch root collection
const fetchRootCollection = (0, react_1.useCallback)(async ({ projectId }) => {
if (!projectId) {
console.warn("Can't fetch root collection without projectId.");
return;
}
dispatch((0, collectionsSlice_1.setLoading)(true));
try {
const result = await fetchRootCollectionQuery({ projectId }).unwrap();
if (result) {
// Set parentId to null for root collection
const rootCollection = { ...result, parentId: null };
dispatch((0, collectionsSlice_1.setCurrentCollection)(rootCollection));
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Failed fetching root collection");
dispatch((0, collectionsSlice_1.handleError)());
}
finally {
dispatch((0, collectionsSlice_1.setLoading)(false));
}
}, [dispatch, fetchRootCollectionQuery]);
// Fetch sub-collections
const fetchSubCollections = (0, react_1.useCallback)(async ({ projectId, collectionId }) => {
if (!projectId || !collectionId) {
console.warn("Can't fetch sub-collections without projectId and collectionId.");
return;
}
dispatch((0, collectionsSlice_1.setLoading)(true));
try {
const result = await fetchSubCollectionsQuery({ projectId, collectionId }).unwrap();
if (result) {
dispatch((0, collectionsSlice_1.setSubCollections)({ collections: result, parentCollectionId: collectionId }));
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Failed fetching sub-collections");
dispatch((0, collectionsSlice_1.handleError)());
}
finally {
dispatch((0, collectionsSlice_1.setLoading)(false));
}
}, [dispatch, fetchSubCollectionsQuery]);
// Create collection
const createCollection = (0, react_1.useCallback)(async ({ projectId, parentCollectionId, collectionName, }) => {
if (!projectId || !parentCollectionId || !collectionName) {
console.error("Missing required parameters for creating collection.");
return;
}
try {
const result = await createCollectionMutation({
projectId,
parentCollectionId,
collectionName,
}).unwrap();
if (result) {
dispatch((0, collectionsSlice_1.addNewCollectionAndNavigate)(result));
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Failed to create collection");
}
}, [createCollectionMutation, dispatch]);
// Update collection
const updateCollection = (0, react_1.useCallback)(async ({ projectId, collectionId, update, }) => {
if (!projectId || !collectionId) {
console.error("Missing required parameters for updating collection.");
return;
}
try {
const result = await updateCollectionMutation({
projectId,
collectionId,
update,
}).unwrap();
if (result) {
// Check if it's the current collection or a sub-collection
dispatch((0, collectionsSlice_1.updateCollectionInSubCollections)(result));
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Failed to update collection");
}
}, [updateCollectionMutation, dispatch]);
// Delete collection
const deleteCollection = (0, react_1.useCallback)(async ({ projectId, collection, }) => {
if (!projectId || !collection) {
console.error("Missing required parameters for deleting collection.");
return;
}
try {
await deleteCollectionMutation({
projectId,
collectionId: collection.id,
}).unwrap();
dispatch((0, collectionsSlice_1.handleCollectionDeletion)({ collectionId: collection.id, parentId: collection.parentId }));
}
catch (err) {
(0, handleError_1.handleError)(err, "Failed to delete collection");
}
}, [deleteCollectionMutation, dispatch]);
// Add entity to collection — optimistically prepends to Redux state, reverts on error
const addToCollection = (0, react_1.useCallback)(async ({ projectId, collectionId, entity, }) => {
if (!projectId || !collectionId || !entity?.id) {
console.error("Missing required parameters for adding to collection.");
return;
}
dispatch((0, collectionsSlice_1.prependCollectionEntity)({ collectionId, entity }));
try {
await addToCollectionMutation({
projectId,
collectionId,
entityId: entity.id,
}).unwrap();
}
catch (err) {
dispatch((0, collectionsSlice_1.removeCollectionEntity)({ collectionId, entityId: entity.id }));
(0, handleError_1.handleError)(err, "Failed to add entity to collection");
throw err;
}
}, [addToCollectionMutation, dispatch]);
// Remove entity from collection — optimistically removes from Redux state, reverts on error
const removeFromCollection = (0, react_1.useCallback)(async ({ projectId, collectionId, entityId, }) => {
if (!projectId || !collectionId || !entityId) {
console.error("Missing required parameters for removing from collection.");
return;
}
const currentList = entitiesByCollectionIdRef.current[collectionId] ?? [];
const originalIndex = currentList.findIndex((e) => e.id === entityId);
const entityToRestore = originalIndex !== -1 ? currentList[originalIndex] : undefined;
dispatch((0, collectionsSlice_1.removeCollectionEntity)({ collectionId, entityId }));
try {
await removeFromCollectionMutation({
projectId,
collectionId,
entityId,
}).unwrap();
}
catch (err) {
if (entityToRestore) {
dispatch((0, collectionsSlice_1.insertCollectionEntityAt)({ collectionId, entity: entityToRestore, index: originalIndex }));
}
(0, handleError_1.handleError)(err, "Failed to remove entity from collection");
throw err;
}
}, [removeFromCollectionMutation, dispatch]);
// Reset collections
const resetCollectionsAction = (0, react_1.useCallback)(() => {
dispatch((0, collectionsSlice_1.resetCollections)());
}, [dispatch]);
return (0, react_1.useMemo)(() => ({
// Navigation
openCollection: openCollectionAction,
goBack: goBackAction,
goToRoot: goToRootAction,
// Data fetching
fetchRootCollection,
fetchSubCollections,
// CRUD operations
createCollection,
updateCollection,
deleteCollection,
addToCollection,
removeFromCollection,
// Utility
resetCollections: resetCollectionsAction,
}), [
openCollectionAction,
goBackAction,
goToRootAction,
fetchRootCollection,
fetchSubCollections,
createCollection,
updateCollection,
deleteCollection,
addToCollection,
removeFromCollection,
resetCollectionsAction,
]);
}
exports.default = useCollectionsActions;
//# sourceMappingURL=useCollectionsActions.js.map