Files
2024-02-08 10:42:35 -05:00

192 lines
5.6 KiB
TypeScript

import React, { useCallback, useMemo } from 'react';
import {
changeViewStyle,
filterByField,
groupByField,
sortByField,
} from '@staticcms/core/actions/entries';
import useTranslate from '@staticcms/core/lib/hooks/useTranslate';
import {
getSortableFields,
getViewFilters,
getViewGroups,
} from '@staticcms/core/lib/util/collection.util';
import { selectCollections } from '@staticcms/core/reducers/selectors/collections';
import {
selectEntriesFilter,
selectEntriesGroup,
selectEntriesSort,
selectViewStyle,
} from '@staticcms/core/reducers/selectors/entries';
import { useAppDispatch, useAppSelector } from '@staticcms/core/store/hooks';
import Card from '../common/card/Card';
import collectionClasses from './Collection.classes';
import CollectionControls from './CollectionControls';
import CollectionHeader from './CollectionHeader';
import EntriesCollection from './entries/EntriesCollection';
import EntriesSearch from './entries/EntriesSearch';
import type {
CollectionWithDefaults,
SortDirection,
ViewFilterWithDefaults,
ViewGroupWithDefaults,
} from '@staticcms/core';
import type { ViewStyle } from '@staticcms/core/constants/views';
import type { FC } from 'react';
import './Collection.css';
export interface CollectionViewProps {
isSearchResults?: boolean;
isSingleSearchResult?: boolean;
name?: string;
searchTerm?: string;
filterTerm?: string;
}
const CollectionView: FC<CollectionViewProps> = ({
name: collectionName,
isSearchResults,
isSingleSearchResult,
searchTerm = '',
filterTerm = '',
}) => {
const t = useTranslate();
const dispatch = useAppDispatch();
const collections = useAppSelector(selectCollections);
const collection = useMemo(
() =>
(collectionName ? collections[collectionName] : collections[0]) as
| CollectionWithDefaults
| undefined,
[collectionName, collections],
);
const viewStyle = useAppSelector(selectViewStyle);
const sort = useAppSelector(state => selectEntriesSort(state, collectionName));
const viewFilters = useMemo(() => getViewFilters(collection), [collection]);
const viewGroups = useMemo(() => getViewGroups(collection), [collection]);
const sortableFields = useMemo(() => getSortableFields(collection, t), [collection, t]);
const filter = useAppSelector(state => selectEntriesFilter(state, collection?.name));
const group = useAppSelector(state => selectEntriesGroup(state, collection?.name));
const searchResultKey = useMemo(
() => `collection.collectionTop.searchResults${isSingleSearchResult ? 'InCollection' : ''}`,
[isSingleSearchResult],
);
const entries = useMemo(() => {
if (isSearchResults) {
let searchCollections = collections;
if (isSingleSearchResult) {
const searchCollection = Object.values(collections).filter(c => c === collection);
if (searchCollection.length === 1) {
searchCollections = {
[searchCollection[0].name]: searchCollection[0],
};
}
}
return (
<EntriesSearch
key="search"
collections={searchCollections}
searchTerm={searchTerm}
filterTerm={filterTerm}
viewStyle={viewStyle}
/>
);
}
if (!collection) {
return null;
}
return (
<EntriesCollection collection={collection} viewStyle={viewStyle} filterTerm={filterTerm} />
);
}, [
collection,
collections,
filterTerm,
isSearchResults,
isSingleSearchResult,
searchTerm,
viewStyle,
]);
const onSortClick = useCallback(
async (key: string, direction?: SortDirection) => {
collection && (await dispatch(sortByField(collection, key, direction)));
},
[collection, dispatch],
);
const onFilterClick = useCallback(
async (filter: ViewFilterWithDefaults) => {
collection && (await dispatch(filterByField(collection, filter)));
},
[collection, dispatch],
);
const onGroupClick = useCallback(
async (group: ViewGroupWithDefaults) => {
collection && (await dispatch(groupByField(collection, group)));
},
[collection, dispatch],
);
const onChangeViewStyle = useCallback(
(viewStyle: ViewStyle) => {
dispatch(changeViewStyle(viewStyle));
},
[dispatch],
);
const collectionDescription = collection?.description;
return (
<div className={collectionClasses.root}>
<div className={collectionClasses.content}>
{isSearchResults ? (
<>
<div className={collectionClasses['search-query']}>
<div>{t(searchResultKey, { searchTerm, collection: collection?.label })}</div>
</div>
<CollectionControls viewStyle={viewStyle} onChangeViewStyle={onChangeViewStyle} />
</>
) : (
<>
{collection ? <CollectionHeader collection={collection} /> : null}
<CollectionControls
viewStyle={viewStyle}
onChangeViewStyle={onChangeViewStyle}
sortableFields={sortableFields}
onSortClick={onSortClick}
sort={sort}
viewFilters={viewFilters?.filters ?? []}
viewGroups={viewGroups?.groups ?? []}
onFilterClick={onFilterClick}
onGroupClick={onGroupClick}
filter={filter}
group={group}
/>
</>
)}
</div>
{collectionDescription ? (
<div className={collectionClasses.description}>
<Card className={collectionClasses['description-card']}>{collectionDescription}</Card>
</div>
) : null}
{entries}
</div>
);
};
export default CollectionView;