Add tag sorting
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import {
|
||||
Button,
|
||||
Menu,
|
||||
@@ -7,22 +7,33 @@ import {
|
||||
Divider,
|
||||
useTheme,
|
||||
Searchbar,
|
||||
HelperText,
|
||||
} from 'react-native-paper';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { RootScrollView } from '../components';
|
||||
import styles from '../styles';
|
||||
import { SORT, SORT_DIRECTION } from '../types';
|
||||
import { HOME_SORT, SORT_DIRECTION } from '../types';
|
||||
import { getSortIcon, getViewIcon } from '../utilities';
|
||||
import {
|
||||
RootState,
|
||||
cycleView,
|
||||
toggleSortDirection,
|
||||
setSortDirection,
|
||||
toggleFavoritesOnly,
|
||||
setSort,
|
||||
setFilter,
|
||||
cycleHomeView,
|
||||
toggleHomeSortDirection,
|
||||
setHomeSortDirection,
|
||||
toggleHomeFavoritesOnly,
|
||||
setHomeSort,
|
||||
setHomeFilter,
|
||||
} from '../state';
|
||||
import { MEME_TYPE, memeTypePlural } from '../database';
|
||||
import { MEME_TYPE, Meme, memeTypePlural } from '../database';
|
||||
import { useQuery } from '@realm/react';
|
||||
|
||||
const homeStyles = StyleSheet.create({
|
||||
headerButtonView: {
|
||||
height: 50,
|
||||
},
|
||||
helperText: {
|
||||
marginVertical: 10,
|
||||
},
|
||||
});
|
||||
|
||||
const Home = () => {
|
||||
const theme = useTheme();
|
||||
@@ -40,26 +51,27 @@ const Home = () => {
|
||||
const [sortMenuVisible, setSortMenuVisible] = useState(false);
|
||||
const [filterMenuVisible, setFilterMenuVisible] = useState(false);
|
||||
|
||||
const handleSortModeChange = (newSort: SORT) => {
|
||||
const handleSortModeChange = (newSort: HOME_SORT) => {
|
||||
if (newSort === sort) {
|
||||
dispatch(toggleSortDirection());
|
||||
dispatch(toggleHomeSortDirection());
|
||||
} else {
|
||||
dispatch(setSort(newSort));
|
||||
if (newSort === SORT.TITLE) {
|
||||
dispatch(setSortDirection(SORT_DIRECTION.ASCENDING));
|
||||
dispatch(setHomeSort(newSort));
|
||||
if (newSort === HOME_SORT.TITLE) {
|
||||
dispatch(setHomeSortDirection(SORT_DIRECTION.ASCENDING));
|
||||
} else {
|
||||
dispatch(setSortDirection(SORT_DIRECTION.DESCENDING));
|
||||
dispatch(setHomeSortDirection(SORT_DIRECTION.DESCENDING));
|
||||
}
|
||||
}
|
||||
setSortMenuVisible(false);
|
||||
};
|
||||
|
||||
const handleFilterChange = (newFilter: MEME_TYPE | undefined) => {
|
||||
dispatch(setFilter(newFilter));
|
||||
dispatch(setHomeFilter(newFilter));
|
||||
setFilterMenuVisible(false);
|
||||
};
|
||||
|
||||
const [search, setSearch] = useState('');
|
||||
const memes = useQuery<Meme>('Meme');
|
||||
|
||||
return (
|
||||
<RootScrollView padded>
|
||||
@@ -68,7 +80,12 @@ const Home = () => {
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
<View style={[styles.flexRowSpaceBetween, styles.alignCenter]}>
|
||||
<View
|
||||
style={[
|
||||
styles.flexRowSpaceBetween,
|
||||
styles.alignCenter,
|
||||
homeStyles.headerButtonView,
|
||||
]}>
|
||||
<View style={[styles.flexRow, styles.alignCenter]}>
|
||||
<Menu
|
||||
visible={sortMenuVisible}
|
||||
@@ -82,31 +99,33 @@ const Home = () => {
|
||||
Sort By: {sort}
|
||||
</Button>
|
||||
}>
|
||||
{Object.keys(SORT).map(key => {
|
||||
{Object.keys(HOME_SORT).map(key => {
|
||||
return (
|
||||
<Menu.Item
|
||||
key={key}
|
||||
onPress={() =>
|
||||
handleSortModeChange(SORT[key as keyof typeof SORT])
|
||||
handleSortModeChange(
|
||||
HOME_SORT[key as keyof typeof HOME_SORT],
|
||||
)
|
||||
}
|
||||
title={SORT[key as keyof typeof SORT]}
|
||||
title={HOME_SORT[key as keyof typeof HOME_SORT]}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</View>
|
||||
<View style={styles.flexRow}>
|
||||
<View style={[styles.flexRow, styles.alignCenter]}>
|
||||
<IconButton
|
||||
icon={getViewIcon(view)}
|
||||
iconColor={theme.colors.primary}
|
||||
size={18}
|
||||
onPress={() => dispatch(cycleView())}
|
||||
size={16}
|
||||
onPress={() => dispatch(cycleHomeView())}
|
||||
/>
|
||||
<IconButton
|
||||
icon={favoritesOnly ? 'heart' : 'heart-outline'}
|
||||
iconColor={theme.colors.primary}
|
||||
size={18}
|
||||
onPress={() => dispatch(toggleFavoritesOnly())}
|
||||
size={16}
|
||||
onPress={() => dispatch(toggleHomeFavoritesOnly())}
|
||||
/>
|
||||
<Menu
|
||||
visible={filterMenuVisible}
|
||||
@@ -116,7 +135,7 @@ const Home = () => {
|
||||
onPress={() => setFilterMenuVisible(true)}
|
||||
icon={filter ? 'filter' : 'filter-outline'}
|
||||
iconColor={theme.colors.primary}
|
||||
size={18}
|
||||
size={16}
|
||||
/>
|
||||
}>
|
||||
<Menu.Item
|
||||
@@ -141,6 +160,14 @@ const Home = () => {
|
||||
</View>
|
||||
</View>
|
||||
<Divider />
|
||||
{/* TODO: Meme Views */}
|
||||
{memes.length === 0 && (
|
||||
<View style={styles.alignCenter}>
|
||||
<HelperText type={'info'} style={homeStyles.helperText}>
|
||||
No memes found
|
||||
</HelperText>
|
||||
</View>
|
||||
)}
|
||||
</RootScrollView>
|
||||
);
|
||||
};
|
||||
|
@@ -1,16 +1,35 @@
|
||||
import React, { useState } from 'react';
|
||||
import { DataTable, HelperText, Searchbar } from 'react-native-paper';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import {
|
||||
Button,
|
||||
DataTable,
|
||||
Divider,
|
||||
HelperText,
|
||||
Menu,
|
||||
Searchbar,
|
||||
} from 'react-native-paper';
|
||||
import { useQuery, useRealm } from '@realm/react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { RootScrollView, TagChip } from '../components';
|
||||
import { Tag, deleteTag } from '../database';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import styles from '../styles';
|
||||
import {
|
||||
RootState,
|
||||
setTagsSort,
|
||||
setTagsSortDirection,
|
||||
toggleTagsSortDirection,
|
||||
} from '../state';
|
||||
import { SORT_DIRECTION, TAG_SORT, tagSortQuery } from '../types';
|
||||
import { getSortIcon } from '../utilities';
|
||||
|
||||
const tagStyles = StyleSheet.create({
|
||||
headerButtonView: {
|
||||
height: 50,
|
||||
},
|
||||
helperText: {
|
||||
marginVertical: 10,
|
||||
},
|
||||
view: {
|
||||
tagView: {
|
||||
justifyContent: 'center',
|
||||
maxWidth: '75%',
|
||||
},
|
||||
@@ -18,37 +37,90 @@ const tagStyles = StyleSheet.create({
|
||||
|
||||
const Tags = () => {
|
||||
const realm = useRealm();
|
||||
const sort = useSelector((state: RootState) => state.tags.sort);
|
||||
const sortDirection = useSelector(
|
||||
(state: RootState) => state.tags.sortDirection,
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [sortMenuVisible, setSortMenuVisible] = useState(false);
|
||||
|
||||
const handleSortModeChange = (newSort: TAG_SORT) => {
|
||||
if (newSort === sort) {
|
||||
dispatch(toggleTagsSortDirection());
|
||||
} else {
|
||||
dispatch(setTagsSort(newSort));
|
||||
if (newSort === TAG_SORT.NAME) {
|
||||
dispatch(setTagsSortDirection(SORT_DIRECTION.ASCENDING));
|
||||
} else {
|
||||
dispatch(setTagsSortDirection(SORT_DIRECTION.DESCENDING));
|
||||
}
|
||||
}
|
||||
setSortMenuVisible(false);
|
||||
};
|
||||
|
||||
const [search, setSearch] = useState('');
|
||||
const tags = useQuery<Tag>('Tag').filtered(`name CONTAINS[c] "${search}"`);
|
||||
const tags = useQuery<Tag>('Tag')
|
||||
.filtered(`name CONTAINS[c] "${search}"`)
|
||||
.sorted(tagSortQuery(sort), sortDirection === SORT_DIRECTION.ASCENDING);
|
||||
|
||||
return (
|
||||
<RootScrollView padded style={styles.alignCenter}>
|
||||
<RootScrollView padded>
|
||||
<Searchbar
|
||||
placeholder="Search Tags"
|
||||
value={search}
|
||||
onChangeText={setSearch}
|
||||
/>
|
||||
<View
|
||||
style={[
|
||||
styles.flexRow,
|
||||
styles.alignCenter,
|
||||
tagStyles.headerButtonView,
|
||||
]}>
|
||||
<Menu
|
||||
visible={sortMenuVisible}
|
||||
onDismiss={() => setSortMenuVisible(false)}
|
||||
anchor={
|
||||
<Button
|
||||
onPress={() => setSortMenuVisible(true)}
|
||||
icon={getSortIcon(sort, sortDirection)}
|
||||
contentStyle={styles.flexRowReverse}
|
||||
compact>
|
||||
Sort By: {sort}
|
||||
</Button>
|
||||
}>
|
||||
{Object.keys(TAG_SORT).map(key => {
|
||||
return (
|
||||
<Menu.Item
|
||||
key={key}
|
||||
onPress={() =>
|
||||
handleSortModeChange(TAG_SORT[key as keyof typeof TAG_SORT])
|
||||
}
|
||||
title={TAG_SORT[key as keyof typeof TAG_SORT]}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</View>
|
||||
<Divider />
|
||||
<DataTable>
|
||||
<DataTable.Header>
|
||||
<DataTable.Title>Tag</DataTable.Title>
|
||||
<DataTable.Title numeric>Items</DataTable.Title>
|
||||
</DataTable.Header>
|
||||
{tags.map(tag => (
|
||||
<DataTable.Row
|
||||
key={tag.id.toHexString()}
|
||||
onPress={() => deleteTag(realm, tag)}>
|
||||
<View style={tagStyles.view}>
|
||||
<View style={tagStyles.tagView}>
|
||||
<TagChip tag={tag} />
|
||||
</View>
|
||||
<DataTable.Cell numeric>{tag.memes.length}</DataTable.Cell>
|
||||
<DataTable.Cell numeric>{tag.memesLength}</DataTable.Cell>
|
||||
</DataTable.Row>
|
||||
))}
|
||||
</DataTable>
|
||||
{tags.length === 0 && (
|
||||
<HelperText type={'info'} style={tagStyles.helperText}>
|
||||
No tags found
|
||||
</HelperText>
|
||||
<View style={styles.alignCenter}>
|
||||
<HelperText type={'info'} style={tagStyles.helperText}>
|
||||
No tags found
|
||||
</HelperText>
|
||||
</View>
|
||||
)}
|
||||
</RootScrollView>
|
||||
);
|
||||
|
Reference in New Issue
Block a user