@@ -1,6 +1,5 @@
1import * as need from 'lib/need';
1import * as need from 'lib/need';
2−import ob from 'urbit-ob';
3−import { Box, Row } from '@tlon/indigo-react';
2+import { Box, LoadingSpinner, Row } from '@tlon/indigo-react';
5import Window from 'components/L2/Window/Window';
4import Window from 'components/L2/Window/Window';
6import HeaderPane from 'components/L2/Window/HeaderPane';
5import HeaderPane from 'components/L2/Window/HeaderPane';
@@ -9,31 +8,41 @@ import { useLocalRouter } from 'lib/LocalRouter';
9import View from 'components/View';
8import View from 'components/View';
10import L2BackHeader from 'components/L2/Headers/L2BackHeader';
9import L2BackHeader from 'components/L2/Headers/L2BackHeader';
11import { usePointCursor } from 'store/pointCursor';
10import { usePointCursor } from 'store/pointCursor';
12−import { useCallback, useEffect, useState } from 'react';
11+import { useCallback, useEffect, useMemo, useState } from 'react';
14import './Residents.scss';
13import './Residents.scss';
15−import Sigil from 'components/Sigil';
16import useRoller from 'lib/useRoller';
14import useRoller from 'lib/useRoller';
17import { Ship } from '@urbit/roller-api';
15import { Ship } from '@urbit/roller-api';
16+import { ResidentRow } from './ResidentRow';
19export const Residents = () => {
18export const Residents = () => {
20 const { pop }: any = useLocalRouter();
19 const { pop }: any = useLocalRouter();
21 const { pointCursor } = usePointCursor();
20 const { pointCursor } = usePointCursor();
22− const point = need.point(pointCursor);
21+ const point = useMemo(() => need.point(pointCursor), [pointCursor]);
23− const { api } = useRoller();
22+ const { api, kickPoint } = useRoller();
24 const [sponsoredPoints, setSponsoredPoints] = useState<Ship[]>([]);
23 const [sponsoredPoints, setSponsoredPoints] = useState<Ship[]>([]);
24+ const [loading, setLoading] = useState<boolean>(false);
26 const fetchResidents = useCallback(async () => {
26 const fetchResidents = useCallback(async () => {
27 if (!point) {
27 if (!point) {
31 // TODO: remove this hack once the API is updated
32 // TODO: remove this hack once the API is updated
32 const { residentes, residents } = await api.getSponsoredPoints(point);
33 const { residentes, residents } = await api.getSponsoredPoints(point);
34 setSponsoredPoints((residents || residentes || []).sort());
34 setSponsoredPoints((residents || residentes || []).sort());
35 }, [api, point]);
36 }, [api, point]);
38+ const handleKick = useCallback(
39+ async (point: Ship) => {
40+ await kickPoint(point);
41+ await fetchResidents();
43+ [fetchResidents, kickPoint]
37 useEffect(() => {
46 useEffect(() => {
38 fetchResidents();
47 fetchResidents();
39 }, [fetchResidents]);
48 }, [fetchResidents]);
@@ -56,23 +65,19 @@ export const Residents = () => {
56 </HeaderPane>
65 </HeaderPane>
57 <BodyPane>
66 <BodyPane>
58 <Box className="content-container">
67 <Box className="content-container">
69+ <Box className={'loading'}>
72+ ) : sponsoredPoints.length > 0 ? (
59− <ul className="residents-list">
73+ <ul className="residents-list">
60− {sponsoredPoints.map(sp => (
74+ {sponsoredPoints.map(sp => (
61− <li>
75+ <ResidentRow point={sp} onKick={handleKick} />
62− <Box className="sigil">
76+ ))}
63− <Box className="sigil-container">
77+ </ul>
68− colors={['#000000', '#FFFFFF']}
72− <Box className={'patp'}>{ob.patp(sp)}</Box>
79+ <Box className="no-results">No residents</Box>
77 </BodyPane>
82 </BodyPane>