@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
195 lines • 8.38 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const hooks_1 = require("../../store/hooks");
const collectionsSlice_1 = require("../../store/slices/collectionsSlice");
const useCollectionsActions_1 = require("./useCollectionsActions");
const useProject_1 = __importDefault(require("../projects/useProject"));
const user_1 = require("../user");
const useAxiosPrivate_1 = __importDefault(require("../../config/useAxiosPrivate"));
/**
* Redux-powered hook that provides the exact same interface as useCollectionsData()
* This is a drop-in replacement for the Context-based hook
*/
function useCollections(_ = {}) {
const dispatch = (0, hooks_1.useReplykeDispatch)();
const axios = (0, useAxiosPrivate_1.default)();
// Get external context
const { projectId } = (0, useProject_1.default)();
const { user } = (0, user_1.useUser)();
// Get Redux state
const currentCollection = (0, hooks_1.useReplykeSelector)(collectionsSlice_1.selectCurrentCollection);
const subCollections = (0, hooks_1.useReplykeSelector)(collectionsSlice_1.selectSubCollections);
const loading = (0, hooks_1.useReplykeSelector)(collectionsSlice_1.selectCollectionsLoading);
const subCollectionsMap = (0, hooks_1.useReplykeSelector)(collectionsSlice_1.selectSubCollectionsMap);
const collectionsById = (0, hooks_1.useReplykeSelector)((state) => state.replyke.collections.collectionsById);
const currentProjectId = (0, hooks_1.useReplykeSelector)(collectionsSlice_1.selectCurrentProjectId);
// Get actions
const { openCollection, goBack, goToRoot, fetchRootCollection, fetchSubCollections, createCollection: createCollectionAction, updateCollection: updateCollectionAction, deleteCollection: deleteCollectionAction, addToCollection: addToCollectionAction, removeFromCollection: removeFromCollectionAction, } = (0, useCollectionsActions_1.useCollectionsActions)();
// Update Redux state when project changes
(0, react_1.useEffect)(() => {
if (projectId && projectId !== currentProjectId) {
dispatch((0, collectionsSlice_1.setProjectContext)(projectId));
}
}, [dispatch, projectId, currentProjectId]);
// Fetch root collection when user and project are available.
// Skip if a collection is already loaded for this project — otherwise mounting
// useCollections() per leaf component (e.g. a BookmarkButton in every card)
// hammers /collections/root and trips the rate limit.
(0, react_1.useEffect)(() => {
if (!user || !projectId)
return;
if (currentCollection && currentProjectId === projectId)
return;
fetchRootCollection({ projectId });
}, [fetchRootCollection, user, projectId, currentCollection, currentProjectId]);
// Fetch sub-collections when current collection changes
(0, react_1.useEffect)(() => {
if (!user || !projectId || !currentCollection)
return;
// Check if sub-collections for this collection are already fetched
if (subCollectionsMap[currentCollection.id] !== undefined) {
return; // No need to fetch, we already have the mapping (even if empty)
}
fetchSubCollections({ projectId, collectionId: currentCollection.id });
}, [
fetchSubCollections,
user,
projectId,
currentCollection,
subCollectionsMap,
]);
// Entity membership checker - checks if entity is in any collection (or specific collection if provided)
const isEntitySaved = (0, react_1.useCallback)(async ({ entityId: selectedEntityId, collectionId }) => {
if (!projectId || !selectedEntityId) {
return {
saved: false,
inSpecificCollection: collectionId ? false : undefined,
collections: [],
};
}
try {
const response = await axios.get(`/${projectId}/entities/is-entity-saved`, {
params: { entityId: selectedEntityId },
});
// If specific collection ID provided, check if entity is in that collection
const inSpecificCollection = collectionId
? response.data.collections.some((col) => col.id === collectionId)
: undefined;
return {
saved: response.data.saved,
inSpecificCollection,
collections: response.data.collections,
};
}
catch (err) {
console.error("Error checking if entity is in collection:", err);
return {
saved: false,
inSpecificCollection: collectionId ? false : undefined,
collections: [],
};
}
}, [projectId, axios]);
// Wrapped CRUD operations that match the original interface
const handleCreateCollection = (0, react_1.useCallback)(async ({ collectionName }) => {
if (!collectionName) {
console.error("No collectionName provided.");
return;
}
if (!currentCollection) {
console.error("No current collection.");
return;
}
if (!projectId) {
console.error("No projectId available.");
return;
}
await createCollectionAction({
projectId,
parentCollectionId: currentCollection.id,
collectionName,
});
}, [createCollectionAction, currentCollection, projectId]);
const handleUpdateCollection = (0, react_1.useCallback)(async ({ collectionId, update }) => {
if (!projectId) {
console.error("No projectId available.");
return;
}
await updateCollectionAction({ projectId, collectionId, update });
}, [updateCollectionAction, projectId]);
const handleDeleteCollection = (0, react_1.useCallback)(async ({ collection }) => {
if (!projectId) {
console.error("No projectId available.");
return;
}
await deleteCollectionAction({ projectId, collection });
}, [deleteCollectionAction, projectId]);
const handleAddToCollection = (0, react_1.useCallback)(async ({ entity }) => {
if (!entity?.id) {
console.error("No entity provided.");
return;
}
if (!currentCollection) {
console.error("No current collection.");
return;
}
if (!projectId) {
console.error("No projectId available.");
return;
}
await addToCollectionAction({
projectId,
collectionId: currentCollection.id,
entity,
});
}, [addToCollectionAction, currentCollection, projectId]);
const handleRemoveFromCollection = (0, react_1.useCallback)(async ({ entityId }) => {
if (!currentCollection) {
console.error("No current collection.");
return;
}
if (!projectId) {
console.error("No projectId available.");
return;
}
await removeFromCollectionAction({
projectId,
collectionId: currentCollection.id,
entityId,
});
}, [removeFromCollectionAction, currentCollection, projectId]);
// Return the same interface as the original hook
return (0, react_1.useMemo)(() => ({
currentCollection,
subCollections,
loading,
openCollection,
goBack,
goToRoot,
isEntitySaved,
createCollection: handleCreateCollection,
updateCollection: handleUpdateCollection,
deleteCollection: handleDeleteCollection,
addToCollection: handleAddToCollection,
removeFromCollection: handleRemoveFromCollection,
}), [
currentCollection,
subCollections,
loading,
openCollection,
goBack,
goToRoot,
isEntitySaved,
handleCreateCollection,
handleUpdateCollection,
handleDeleteCollection,
handleAddToCollection,
handleRemoveFromCollection,
]);
}
exports.default = useCollections;
//# sourceMappingURL=useCollections.js.map