@@ -1,5 +1,6 @@
1import React, { useState, useEffect, useCallback, useMemo } from 'react';
1import React, { useState, useEffect, useCallback, useMemo } from 'react';
2+import cn from 'classnames';
2−import { Grid, H4, HelpText } from 'indigo-react';
3+import { Grid, H4, HelpText, Flex } from 'indigo-react';
3import { Just, Nothing } from 'folktale/maybe';
4import { Just, Nothing } from 'folktale/maybe';
4import * as ob from 'urbit-ob';
5import * as ob from 'urbit-ob';
@@ -32,15 +33,31 @@ const VIEWS = {
32 [NAMES.ALL]: Tab,
33 [NAMES.ALL]: Tab,
35−function Tab({ className, points, onAccept, onDecline }) {
38+function Tab({ className, points, onAccept, onDecline, page, setPage }) {
39+ const start = page * PAGE_SIZE;
40+ const end = page * PAGE_SIZE + PAGE_SIZE;
41+ const pointsCount = points.map(ps => ps.length).getOrElse(0);
42+ const maxPage = Math.ceil(pointsCount / PAGE_SIZE) - 1;
43+ const hasNext = page < maxPage;
44+ const hasPrev = page > 0;
45+ const _points = points.map(ps => ps.slice(start, end)).getOrElse([]);
47+ const onNext = useCallback(() => {
51+ const onPrev = useCallback(() => {
36 if (Nothing.hasInstance(points)) {
55 if (Nothing.hasInstance(points)) {
37 return <Grid className={className}></Grid>;
56 return <Grid className={className}></Grid>;
40− const _points = points.getOrElse([]);
43− <Grid className={className}>
60+ <Grid className={cn('mt2', className)}>
44 {_points.length === 0 && (
61 {_points.length === 0 && (
45 <Grid.Item full as={HelpText} className="mt8 t-center">
62 <Grid.Item full as={HelpText} className="mt8 t-center">
46 {Just.hasInstance(points) ? (
63 {Just.hasInstance(points) ? (
@@ -61,6 +78,28 @@ function Tab({ className, points, onAccept, onDecline }) {
61 onDecline={onDecline}
78 onDecline={onDecline}
84+ className="pointer underline mt4"
91+ <Grid.Item className="mt6 ml7 t-center gray3" cols={[4, 10]}>
92+ <span className="black">Page {page + 1}</span> of {maxPage + 1}
97+ className="pointer underline t-right mt4"
@@ -83,7 +122,7 @@ function Resident({ point, onAccept, onDecline }) {
83 <Sigil patp={patp} size={25} colors={['#FFFFFF', '#000000']} />
122 <Sigil patp={patp} size={25} colors={['#FFFFFF', '#000000']} />
85 </Grid.Item>
124 </Grid.Item>
86− <Grid.Item className="flex-row align-center" cols={[3, 6]}>
125+ <Grid.Item className="flex-row align-center" cols={[3, 7]}>
87 {patp}{' '}
126 {patp}{' '}
88 </Grid.Item>
127 </Grid.Item>
89 {isRequest && (
128 {isRequest && (
@@ -121,7 +160,16 @@ export default function Residents() {
122 const { residents, requests } = getResidents(point);
161 const { residents, requests } = getResidents(point);
124− const [currentTab, setCurrentTab] = useState(NAMES.ALL);
163+ const [currentTab, _setCurrentTab] = useState(NAMES.ALL);
164+ const [page, setPage] = useState(0);
166+ const setCurrentTab = useCallback(
169+ _setCurrentTab(tab);
171+ [setPage, _setCurrentTab]
126 const isRequests = useMemo(() => currentTab === NAMES.REQUESTS, [currentTab]);
174 const isRequests = useMemo(() => currentTab === NAMES.REQUESTS, [currentTab]);
@@ -169,6 +217,8 @@ export default function Residents() {
169 points={points}
217 points={points}
170 onAccept={onAccept}
218 onAccept={onAccept}
171 onDecline={onDecline}
219 onDecline={onDecline}