on 8d566ea help sign in
bridge/src/views/Residents.js
172 lines 4.3 kB history raw
1import React, { useState, useEffect, useCallback, useMemo } from 'react';
2import { Grid, H4, HelpText } from 'indigo-react';
3import { Just, Nothing } from 'folktale/maybe';
4import * as ob from 'urbit-ob';
6import View from 'components/View';
7import Tabs from 'components/Tabs';
8import Crumbs from 'components/Crumbs';
9import Sigil from 'components/Sigil';
10import Blinky from 'components/Blinky';
11import NavHeader from 'components/NavHeader';
13import { useLocalRouter } from 'lib/LocalRouter';
14import useCurrentPointName from 'lib/useCurrentPointName';
15import * as need from 'lib/need';
17import { usePointCursor } from 'store/pointCursor';
18import { usePointCache } from 'store/pointCache';
20const NAMES = {
21 REQUESTS: 'REQUESTS',
22 ALL: 'ALL',
23};
25const OPTIONS = [
26 { text: 'Requests', value: NAMES.REQUESTS },
27 { text: 'All', value: NAMES.ALL },
28];
30const VIEWS = {
31 [NAMES.REQUESTS]: Tab,
32 [NAMES.ALL]: Tab,
33};
35function Tab({ className, points, onAccept, onDecline }) {
36 if (Nothing.hasInstance(points)) {
37 return <Grid className={className}></Grid>;
38 }
40 const _points = points.getOrElse([]);
42 return (
43 <Grid className={className}>
44 {_points.length === 0 && (
45 <Grid.Item full as={HelpText} className="mt8 t-center">
46 {Just.hasInstance(points) ? (
47 'No points to display'
48 ) : (
49 <>
50 <Blinky /> Loading...
51 </>
52 )}
53 </Grid.Item>
54 )}
56 {_points.map(point => (
57 <Resident
58 key={point}
59 point={point}
60 onAccept={onAccept}
61 onDecline={onDecline}
62 />
63 ))}
64 </Grid>
65 );
68function Resident({ point, onAccept, onDecline }) {
69 const patp = ob.patp(point);
70 const sigilSize = 50;
72 const isRequest = onAccept && onDecline;
74 return (
75 <>
76 <Grid.Item className="flex-row justify-center align-center" cols={[1, 3]}>
77 <div
78 style={{
79 display: 'inline-block',
80 height: `${sigilSize}px`,
81 width: `${sigilSize}px`,
82 }}>
83 <Sigil patp={patp} size={25} colors={['#FFFFFF', '#000000']} />
84 </div>
85 </Grid.Item>
86 <Grid.Item className="flex-row align-center" cols={[3, 6]}>
87 {patp}{' '}
88 </Grid.Item>
89 {isRequest && (
90 <>
91 <Grid.Item
92 className="flex-row-r align-center underline green3 pointer"
93 cols={[7, 10]}
94 onClick={() => onAccept(point)}>
95 Accept
96 </Grid.Item>
97 <Grid.Item
98 className="flex-row-r align-center underline red4 pointer"
99 cols={[10, 13]}
100 onClick={() => onDecline(point)}>
101 Decline
102 </Grid.Item>
103 </>
104 )}
105 <Grid.Divider />
106 </>
107 );
110export default function Residents() {
111 const { pop, push, names } = useLocalRouter();
112 const name = useCurrentPointName();
114 const { pointCursor } = usePointCursor();
115 const point = need.point(pointCursor);
116 const { getResidents, syncResidents } = usePointCache();
118 useEffect(() => {
119 syncResidents(point);
120 }, [syncResidents, point]);
122 const { residents, requests } = getResidents(point);
124 const [currentTab, setCurrentTab] = useState(NAMES.ALL);
126 const isRequests = useMemo(() => currentTab === NAMES.REQUESTS, [currentTab]);
128 const _onAccept = useCallback(adoptee =>
129 push(names.ADOPT, {
130 adoptee,
131 denied: false,
132 })
133 );
134 const onAccept = isRequests && _onAccept;
136 const _onDecline = useCallback(adoptee =>
137 push(names.ADOPT, {
138 adoptee,
139 denied: true,
140 })
141 );
142 const onDecline = isRequests && _onDecline;
144 const points = isRequests ? requests : residents;
146 return (
147 <View pop={pop} inset>
148 <NavHeader>
149 <Crumbs routes={[{ text: name, action: pop }, { text: 'Residents' }]} />
150 </NavHeader>
151 <Grid>
152 <Grid.Item full as={H4} className="mt4">
153 Residents
154 </Grid.Item>
155 <Grid.Item
156 full
157 className="mt1"
158 as={Tabs}
159 // Tabs
160 views={VIEWS}
161 options={OPTIONS}
162 currentTab={currentTab}
163 onTabChange={setCurrentTab}
164 // Props for tab
165 points={points}
166 onAccept={onAccept}
167 onDecline={onDecline}
168 />
169 </Grid>
170 </View>
171 );