2023-12-13 14:32:57 +03:00
|
|
|
'use client';
|
|
|
|
|
2023-11-26 02:24:16 +03:00
|
|
|
import { useCallback, useLayoutEffect, useState } from 'react';
|
|
|
|
|
2023-12-13 14:32:57 +03:00
|
|
|
import { ConceptLoader } from '@/components/Common/ConceptLoader';
|
|
|
|
import InfoError from '@/components/InfoError';
|
|
|
|
import { useAuth } from '@/context/AuthContext';
|
|
|
|
import { useLibrary } from '@/context/LibraryContext';
|
2023-12-26 14:23:51 +03:00
|
|
|
import { useConceptNavigation } from '@/context/NavigationContext';
|
2023-12-13 14:32:57 +03:00
|
|
|
import { useConceptTheme } from '@/context/ThemeContext';
|
|
|
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
|
|
|
import useQueryStrings from '@/hooks/useQueryStrings';
|
|
|
|
import { ILibraryItem } from '@/models/library';
|
2023-12-26 14:23:51 +03:00
|
|
|
import { ILibraryFilter, LibraryFilterStrategy } from '@/models/miscellaneous';
|
2023-12-13 14:32:57 +03:00
|
|
|
|
2023-11-26 02:24:16 +03:00
|
|
|
import SearchPanel from './SearchPanel';
|
|
|
|
import ViewLibrary from './ViewLibrary';
|
|
|
|
|
|
|
|
function LibraryPage() {
|
2023-12-13 14:32:57 +03:00
|
|
|
const router = useConceptNavigation();
|
|
|
|
const urlParams = useQueryStrings();
|
|
|
|
const searchFilter = (urlParams.get('filter') || null) as LibraryFilterStrategy | null;
|
|
|
|
|
|
|
|
const { user } = useAuth();
|
|
|
|
|
2023-11-26 02:24:16 +03:00
|
|
|
const library = useLibrary();
|
|
|
|
const { setShowScroll } = useConceptTheme();
|
|
|
|
|
2023-12-05 01:22:44 +03:00
|
|
|
const [filter, setFilter] = useState<ILibraryFilter>({});
|
|
|
|
const [items, setItems] = useState<ILibraryItem[]>([]);
|
2023-11-26 02:24:16 +03:00
|
|
|
|
|
|
|
const [query, setQuery] = useState('');
|
|
|
|
const [strategy, setStrategy] = useLocalStorage<LibraryFilterStrategy>('search_strategy', LibraryFilterStrategy.MANUAL);
|
|
|
|
|
2023-12-13 14:32:57 +03:00
|
|
|
useLayoutEffect(() => {
|
|
|
|
if (searchFilter === null) {
|
|
|
|
router.replace(`/library?filter=${strategy}`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const inputStrategy = searchFilter && Object.values(LibraryFilterStrategy).includes(searchFilter) ? searchFilter : LibraryFilterStrategy.MANUAL;
|
|
|
|
setQuery('');
|
|
|
|
setStrategy(inputStrategy);
|
|
|
|
setFilter(ApplyStrategy(inputStrategy));
|
|
|
|
}, [user, router, setQuery, setFilter, setStrategy, strategy, searchFilter]);
|
|
|
|
|
2023-11-26 02:24:16 +03:00
|
|
|
useLayoutEffect(
|
|
|
|
() => {
|
|
|
|
setShowScroll(true);
|
|
|
|
return () => setShowScroll(false);
|
|
|
|
}, [setShowScroll]);
|
|
|
|
|
|
|
|
useLayoutEffect(
|
|
|
|
() => {
|
|
|
|
setItems(library.applyFilter(filter));
|
|
|
|
}, [library, filter, filter.query]);
|
|
|
|
|
|
|
|
const resetQuery = useCallback(
|
|
|
|
() => {
|
|
|
|
setQuery('');
|
|
|
|
setFilter({});
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
return (
|
2023-11-27 11:33:34 +03:00
|
|
|
<>
|
|
|
|
{library.loading ? <ConceptLoader/> : null}
|
2023-12-13 14:32:57 +03:00
|
|
|
{library.error ? <InfoError error={library.error}/> : null}
|
2023-11-27 11:33:34 +03:00
|
|
|
{(!library.loading && library.items) ?
|
2023-12-05 01:22:44 +03:00
|
|
|
<>
|
2023-11-27 11:33:34 +03:00
|
|
|
<SearchPanel
|
|
|
|
query={query}
|
|
|
|
setQuery={setQuery}
|
|
|
|
strategy={strategy}
|
|
|
|
total={library.items.length ?? 0}
|
|
|
|
filtered={items.length}
|
|
|
|
setFilter={setFilter}
|
|
|
|
/>
|
|
|
|
<ViewLibrary
|
|
|
|
resetQuery={resetQuery}
|
|
|
|
items={items}
|
|
|
|
/>
|
2023-12-05 01:22:44 +03:00
|
|
|
</> : null}
|
2023-11-27 11:33:34 +03:00
|
|
|
</>);
|
2023-11-26 02:24:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
export default LibraryPage;
|
2023-12-13 14:32:57 +03:00
|
|
|
|
|
|
|
// ====== Internals =======
|
|
|
|
function ApplyStrategy(strategy: LibraryFilterStrategy): ILibraryFilter {
|
|
|
|
switch (strategy) {
|
|
|
|
case LibraryFilterStrategy.MANUAL: return {};
|
|
|
|
case LibraryFilterStrategy.COMMON: return { is_common: true };
|
|
|
|
case LibraryFilterStrategy.CANONICAL: return { is_canonical: true };
|
|
|
|
case LibraryFilterStrategy.PERSONAL: return { is_personal: true };
|
|
|
|
case LibraryFilterStrategy.SUBSCRIBE: return { is_subscribed: true };
|
|
|
|
case LibraryFilterStrategy.OWNED: return { is_owned: true };
|
|
|
|
}
|
|
|
|
}
|