@@ -17,7 +18,7 @@ const HomeCard = ({ title, type, text, author, image }) => (
);
const Home = ({ selected }) => {
- const homeItems = Store.useState(s => s.homeItems);
+ const homeItems = Store.useState(selectors.getHomeItems);
return (
diff --git a/components/pages/ListDetail.jsx b/components/pages/ListDetail.jsx
new file mode 100644
index 0000000..54e597b
--- /dev/null
+++ b/components/pages/ListDetail.jsx
@@ -0,0 +1,60 @@
+import Store from '../../store';
+import * as actions from '../../store/actions';
+import * as selectors from '../../store/selectors';
+
+import Content from '../ui/Content';
+import List from '../ui/List';
+import VirtualScroll from '../ui/VirtualScroll';
+
+const ListItems = ({ list, onClose }) => {
+ return (
+ <>
+
+ }
+ />
+ >
+ );
+};
+
+const ListItemEntry = ({ list, item }) => (
+
+ {item.name}
+ {
+ actions.setDone(list, item, !item.done);
+ }}
+ />
+
+);
+
+const ListDetail = ({ selected }) => {
+ const selectedList = Store.useState(selectors.getSelectedList);
+
+ return (
+
+
+ {selected && (
+ {
+ actions.setSelectedList(null);
+ actions.setPageById('lists');
+ }}
+ />
+ )}
+
+
+ );
+};
+
+export default ListDetail;
diff --git a/components/pages/Lists.jsx b/components/pages/Lists.jsx
index 6f9237d..42d92fb 100644
--- a/components/pages/Lists.jsx
+++ b/components/pages/Lists.jsx
@@ -1,11 +1,9 @@
-import { useState } from 'react';
import Store from '../../store';
-import { setDone } from '../../store/actions';
-import Card from '../ui/Card';
+import * as actions from '../../store/actions';
+import * as selectors from '../../store/selectors';
import Content from '../ui/Content';
import List from '../ui/List';
-import ListItem from '../ui/ListItem';
import VirtualScroll from '../ui/VirtualScroll';
const ListEntry = ({ list, ...props }) => (
@@ -15,7 +13,7 @@ const ListEntry = ({ list, ...props }) => (
);
const AllLists = ({ onSelect }) => {
- const lists = Store.useState(s => s.lists);
+ const lists = Store.useState(selectors.getLists);
return (
{
);
};
-const ListItems = ({ list, onClose }) => {
- return (
- <>
-
- }
- />
- >
- );
-};
-
-const ListItemEntry = ({ list, item }) => (
-
- {item.name}
- {
- setDone(list, item, !item.done);
- }}
- />
-
-);
-
-const Feed = ({ selected }) => {
- const selectedList = Store.useState(s => s.selectedList);
-
+const Lists = ({ selected }) => {
return (
- {selected && selectedList ? (
-
- Store.update(s => {
- s.selectedList = null;
- })
- }
- />
- ) : (
+ {selected && (
{
- Store.update(s => {
- s.selectedList = list;
- });
+ actions.setSelectedList(list);
+ actions.setPageById('list-detail');
}}
/>
)}
@@ -89,4 +44,4 @@ const Feed = ({ selected }) => {
);
};
-export default Feed;
+export default Lists;
diff --git a/components/ui/Nav.jsx b/components/ui/Nav.jsx
index e43d155..d960f6c 100644
--- a/components/ui/Nav.jsx
+++ b/components/ui/Nav.jsx
@@ -1,10 +1,12 @@
import { useEffect, useState } from 'react';
import { Plugins } from '@capacitor/core';
-import Store from '../../store';
+import * as actions from '../../store/actions';
const Nav = ({ page }) => {
- const [showMenu, setShowMenu] = useState(false);
+ const [showProfileMenu, setShowProfileMenu] = useState(false);
+
+ const title = typeof page.title === 'function' ? page.title() : page.title;
useEffect(() => {
Plugins.StatusBar.setStyle({
@@ -23,11 +25,7 @@ const Nav = ({ page }) => {
- Store.update(s => {
- s.showMenu = true;
- })
- }
+ onClick={() => actions.setMenuOpen(true)}
>
{/* Mobile menu button*/}
{
-
{page.title}
+ {title}
@@ -116,11 +114,7 @@ const Nav = ({ page }) => {
- Store.update(s => {
- s.showNotifications = true;
- })
- }
+ onClick={() => actions.setNotificationsOpen(true)}
>
View notifications
{/* Heroicon name: bell */}
@@ -148,7 +142,7 @@ const Nav = ({ page }) => {
className="bg-gray-800 flex text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white"
id="user-menu"
aria-haspopup="true"
- onClick={() => setShowMenu(!showMenu)}
+ onClick={() => setShowProfileMenu(!showProfileMenu)}
>
Open user menu
{
*/}
{
- const pages = Store.useState(s => s.pages);
+ const pages = Store.useState(selectors.getPages);
return (
@@ -29,37 +30,25 @@ const CurrentPage = ({ page }) => {
};
export default function Index() {
- const showMenu = Store.useState(s => s.showMenu);
- const showNotifications = Store.useState(s => s.showNotifications);
- const currentPage = Store.useState(s => s.currentPage);
- const pages = Store.useState(s => s.pages);
+ const showMenu = Store.useState(selectors.getMenuOpen);
+ const showNotifications = Store.useState(selectors.getNotificationsOpen);
+ const currentPage = Store.useState(selectors.getCurrentPage);
+ const tabs = Store.useState(selectors.getTabs);
- const closeMenu = () => {
- Store.update(s => {
- s.showMenu = false;
- });
- };
+ const closeMenu = () => actions.setMenuOpen(false);
const backdropClose = () => {
- Store.update(s => {
- s.showMenu = false;
- s.showNotifications = false;
- });
+ actions.setMenuOpen(false);
+ actions.setNotificationsOpen(false);
};
- const closeNotifications = () => {
- Store.update(s => {
- s.showNotifications = false;
- });
- };
+ const closeNotifications = () => actions.setNotificationsOpen(false);
// To enable edge drag detection to open the side menu
const bind = useDrag(
({ down, movement: [mx], xy: [x, y], cancel }) => {
if (mx > 5 && x < 50 && down) {
- Store.update(s => {
- s.showMenu = true;
- });
+ actions.setMenuOpen(true);
cancel();
}
},
@@ -84,15 +73,11 @@ export default function Index() {
- {pages.map(p => (
+ {tabs.map(p => (
- Store.update(s => {
- s.currentPage = p;
- })
- }
+ onClick={() => actions.setPage(p)}
selected={p.id === currentPage.id}
/>
))}
diff --git a/store/actions.js b/store/actions.js
index 080516d..05f2f10 100644
--- a/store/actions.js
+++ b/store/actions.js
@@ -1,5 +1,31 @@
import Store from '.';
+export const setPageById = id => {
+ Store.update((s, o) => {
+ s.currentPage = o.pages.find(p => p.id === id);
+ });
+};
+
+export const setPage = page => {
+ Store.update((s, o) => {
+ s.currentPage = page;
+ });
+};
+
+export const setMenuOpen = open => {
+ Store.update(s => {
+ s.menuOpen = open;
+ });
+};
+
+export const setNotificationsOpen = open => {
+ Store.update(s => {
+ s.notificationsOpen = open;
+ });
+};
+
+// App-specific actions
+
export const setDone = (list, item, done) => {
Store.update((s, o) => {
const listIndex = o.lists.findIndex(l => l === list);
@@ -10,3 +36,9 @@ export const setDone = (list, item, done) => {
}
});
};
+
+export const setSelectedList = list => {
+ Store.update(s => {
+ s.selectedList = list;
+ });
+};
diff --git a/store/index.js b/store/index.js
index 563d930..eb3efcf 100644
--- a/store/index.js
+++ b/store/index.js
@@ -5,6 +5,7 @@ import { list, listOutline, cog, cogOutline, home, homeOutline } from 'ionicons/
import Home from '../components/pages/Home';
import Lists from '../components/pages/Lists';
import Settings from '../components/pages/Settings';
+import ListDetail from '../components/pages/ListDetail';
// The available pages here
const pages = [
@@ -16,6 +17,13 @@ const pages = [
selectedIcon: list,
component: Lists,
},
+ {
+ id: 'list-detail',
+ title: () => Store.getRawState().selectedList?.name,
+ icon: listOutline,
+ selectedIcon: list,
+ component: ListDetail,
+ },
{
id: 'settings',
title: 'Settings',
@@ -81,10 +89,16 @@ const lists = [
const Store = new PullStateStore({
safeAreaTop: 0,
safeAreaBottom: 0,
- showMenu: false,
- showNotifications: false,
+ menuOpen: false,
+ notificationsOpen: false,
currentPage: pages[0],
pages,
+
+ // The pages that are linked to tabs
+ tabs: pages.filter(p => ['home', 'lists', 'settings'].indexOf(p.id) >= 0),
+ // The pages that are linked to the menu
+ menuLinks: pages.filter(p => ['home', 'lists', 'settings'].indexOf(p.id) >= 0),
+
homeItems,
lists,
selectedList: null,
diff --git a/store/selectors.js b/store/selectors.js
new file mode 100644
index 0000000..1ef2bee
--- /dev/null
+++ b/store/selectors.js
@@ -0,0 +1,15 @@
+import { createSelector } from 'reselect';
+
+const getState = state => state;
+
+export const getMenuOpen = createSelector(getState, state => state.menuOpen);
+export const getNotificationsOpen = createSelector(getState, state => state.notificationsOpen);
+export const getCurrentPage = createSelector(getState, state => state.currentPage);
+export const getTabs = createSelector(getState, state => state.tabs);
+export const getMenuLinks = createSelector(getState, state => state.menuLinks);
+export const getPages = createSelector(getState, state => state.pages);
+
+// App specific selectors
+export const getHomeItems = createSelector(getState, state => state.homeItems);
+export const getLists = createSelector(getState, state => state.lists);
+export const getSelectedList = createSelector(getState, state => state.selectedList);