@@ -1,6 +1,5 @@
11import * 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';
43
54import Window from 'components/L2/Window/Window';
65import HeaderPane from 'components/L2/Window/HeaderPane';
@@ -9,31 +8,41 @@ import { useLocalRouter } from 'lib/LocalRouter';
98import View from 'components/View';
109import L2BackHeader from 'components/L2/Headers/L2BackHeader';
1110import { usePointCursor } from 'store/pointCursor';
12−import { useCallback, useEffect, useState } from 'react';
11+import { useCallback, useEffect, useMemo, useState } from 'react';
1312
1413import './Residents.scss';
15−import Sigil from 'components/Sigil';
1614import useRoller from 'lib/useRoller';
1715import { Ship } from '@urbit/roller-api';
16+import { ResidentRow } from './ResidentRow';
1817
1918export const Residents = () => {
2019 const { pop }: any = useLocalRouter();
2120 const { pointCursor } = usePointCursor();
22− const point = need.point(pointCursor);
23− const { api } = useRoller();
21+ const point = useMemo(() => need.point(pointCursor), [pointCursor]);
22+ const { api, kickPoint } = useRoller();
2423 const [sponsoredPoints, setSponsoredPoints] = useState<Ship[]>([]);
24+ const [loading, setLoading] = useState<boolean>(false);
2525
2626 const fetchResidents = useCallback(async () => {
2727 if (!point) {
2828 return;
2929 }
3030
31+ setLoading(true);
3132 // TODO: remove this hack once the API is updated
3233 const { residentes, residents } = await api.getSponsoredPoints(point);
33−
3434 setSponsoredPoints((residents || residentes || []).sort());
35+ setLoading(false);
3536 }, [api, point]);
3637
38+ const handleKick = useCallback(
39+ async (point: Ship) => {
40+ await kickPoint(point);
41+ await fetchResidents();
42+ },
43+ [fetchResidents, kickPoint]
44+ );
45+
3746 useEffect(() => {
3847 fetchResidents();
3948 }, [fetchResidents]);
@@ -56,23 +65,19 @@ export const Residents = () => {
5665 </HeaderPane>
5766 <BodyPane>
5867 <Box className="content-container">
59− <ul className="residents-list">
60− {sponsoredPoints.map(sp => (
61− <li>
62− <Box className="sigil">
63− <Box className="sigil-container">
64− <Sigil
65− icon
66− patp={ob.patp(sp)}
67− size={16}
68− colors={['#000000', '#FFFFFF']}
69− />
70− </Box>
71− </Box>
72− <Box className={'patp'}>{ob.patp(sp)}</Box>
73− </li>
74− ))}
75− </ul>
68+ {loading ? (
69+ <Box className={'loading'}>
70+ <LoadingSpinner />
71+ </Box>
72+ ) : sponsoredPoints.length > 0 ? (
73+ <ul className="residents-list">
74+ {sponsoredPoints.map(sp => (
75+ <ResidentRow point={sp} onKick={handleKick} />
76+ ))}
77+ </ul>
78+ ) : (
79+ <Box className="no-results">No residents</Box>
80+ )}
7681 </Box>
7782 </BodyPane>
7883 </Window>