This repository has no description
semble
/
src
/
webapp
/
features
/
connections
/
containers
/
connectionsContainer
/
ConnectionsContainer.tsx
6.8 kB
206 lines
1'use client';
2
3import useForwardConnections from '@/features/connections/lib/queries/useForwardConnections';
4import useBackwardConnections from '@/features/connections/lib/queries/useBackwardConnections';
5import useAllConnections from '@/features/connections/lib/queries/useAllConnections';
6import InfiniteScroll from '@/components/contentDisplay/infiniteScroll/InfiniteScroll';
7import { Box, Grid, Group, Stack } from '@mantine/core';
8import ConnectionsContainerError from './Error.ConnectionsContainer';
9import ConnectionItem from '@/features/connections/components/connectionItem/ConnectionItem';
10import SembleEmptyTab from '@/features/semble/components/sembleEmptyTab/SembleEmptyTab';
11import { BiLink } from 'react-icons/bi';
12import { useDisclosure } from '@mantine/hooks';
13import { ConnectionFilters } from '@/features/connections/components/connectionFilters/ConnectionFilters';
14import DirectionToggle from '@/features/connections/components/connectionFilters/DirectionToggle';
15import { useState } from 'react';
16import { ConnectionType, ConnectionWithSourceAndTarget } from '@semble/types';
17import EditConnectionModal from '@/features/connections/components/editConnectionModal/EditConnectionModal';
18
19type Direction = 'to' | 'from' | 'all';
20
21interface Props {
22 url: string;
23}
24
25export default function ConnectionsContainer(props: Props) {
26 const [modalOpened, { open: openModal, close: closeModal }] =
27 useDisclosure(false);
28
29 const [direction, setDirection] = useState<Direction>('all');
30 const [connectionType, setConnectionType] = useState<ConnectionType | null>(
31 null,
32 );
33 const [connectionToEdit, setConnectionToEdit] = useState<{
34 connection: ConnectionWithSourceAndTarget['connection'];
35 targetUrl: string;
36 } | null>(null);
37
38 const handleOpenEditModal = (
39 connection: ConnectionWithSourceAndTarget['connection'],
40 targetUrl: string,
41 ) => {
42 setConnectionToEdit({ connection, targetUrl });
43 openModal();
44 };
45
46 const handleCloseModal = () => {
47 setConnectionToEdit(null);
48 closeModal();
49 };
50
51 const connectionTypes = connectionType ? [connectionType] : undefined;
52
53 const {
54 data: forwardData,
55 error: forwardError,
56 fetchNextPage: fetchNextForward,
57 hasNextPage: hasNextForward,
58 isFetchingNextPage: isFetchingNextForward,
59 isPending: isPendingForward,
60 } = useForwardConnections({
61 url: props.url,
62 connectionTypes,
63 });
64
65 const {
66 data: backwardData,
67 error: backwardError,
68 fetchNextPage: fetchNextBackward,
69 hasNextPage: hasNextBackward,
70 isFetchingNextPage: isFetchingNextBackward,
71 isPending: isPendingBackward,
72 } = useBackwardConnections({
73 url: props.url,
74 connectionTypes,
75 });
76
77 const {
78 data: allData,
79 error: allError,
80 fetchNextPage: fetchNextAll,
81 hasNextPage: hasNextAll,
82 isFetchingNextPage: isFetchingNextAll,
83 isPending: isPendingAll,
84 } = useAllConnections({
85 url: props.url,
86 connectionTypes,
87 });
88
89 const allForwardConnections =
90 forwardData?.pages.flatMap((page) => page.connections ?? []) ?? [];
91 const allBackwardConnections =
92 backwardData?.pages.flatMap((page) => page.connections ?? []) ?? [];
93 const allConnections =
94 allData?.pages.flatMap((page) => page.connections ?? []) ?? [];
95
96 const emptyMessage =
97 direction === 'all'
98 ? 'No connections found'
99 : `No connections found ${direction} this`;
100
101 if (forwardError || backwardError || allError) {
102 return <ConnectionsContainerError />;
103 }
104
105 const connections =
106 direction === 'to'
107 ? allForwardConnections
108 : direction === 'from'
109 ? allBackwardConnections
110 : allConnections;
111 const fetchNextPage =
112 direction === 'to'
113 ? fetchNextForward
114 : direction === 'from'
115 ? fetchNextBackward
116 : fetchNextAll;
117 const hasNextPage =
118 direction === 'to'
119 ? hasNextForward
120 : direction === 'from'
121 ? hasNextBackward
122 : hasNextAll;
123 const isFetchingNextPage =
124 direction === 'to'
125 ? isFetchingNextForward
126 : direction === 'from'
127 ? isFetchingNextBackward
128 : isFetchingNextAll;
129 const isPending =
130 direction === 'to'
131 ? isPendingForward
132 : direction === 'from'
133 ? isPendingBackward
134 : isPendingAll;
135
136 return (
137 <>
138 <Stack gap={'md'} align="center">
139 <Group justify="space-between" w={'100%'} maw={600}>
140 <DirectionToggle value={direction} onChange={setDirection} />
141 <ConnectionFilters.Root
142 connectionType={connectionType}
143 onConnectionTypeChange={setConnectionType}
144 >
145 <ConnectionFilters.ConnectionTypeFilter />
146 </ConnectionFilters.Root>
147 </Group>
148
149 {connections.length === 0 && !isPending ? (
150 <SembleEmptyTab message={emptyMessage} icon={BiLink} />
151 ) : (
152 <InfiniteScroll
153 dataLength={connections.length}
154 hasMore={!!hasNextPage}
155 isInitialLoading={isPending}
156 isLoading={isFetchingNextPage}
157 loadMore={fetchNextPage}
158 >
159 <Grid gap="xl" mx={'auto'} maw={600} w={'100%'}>
160 {connections.map((connection, index) => {
161 // Determine the actual direction for this specific connection
162 // If direction is 'all', check if the source URL matches props.url
163 const isForward =
164 direction === 'all'
165 ? connection.source.url === props.url
166 : direction === 'to';
167 const connectionDirection = isForward ? 'forward' : 'backward';
168 const targetUrl = isForward
169 ? connection.target.url
170 : connection.source.url;
171
172 return (
173 <Box
174 key={`${direction}-${index}`}
175 style={{
176 contentVisibility: 'auto',
177 containIntrinsicSize: 'auto 200px',
178 }}
179 >
180 <Grid.Col span={12}>
181 <ConnectionItem
182 connection={connection}
183 direction={connectionDirection}
184 onEdit={() => {
185 handleOpenEditModal(connection.connection, targetUrl);
186 }}
187 />
188 </Grid.Col>
189 </Box>
190 );
191 })}
192 </Grid>
193 </InfiniteScroll>
194 )}
195 </Stack>
196
197 <EditConnectionModal
198 isOpen={modalOpened}
199 onClose={handleCloseModal}
200 sourceUrl={props.url}
201 targetUrl={connectionToEdit?.targetUrl}
202 connection={connectionToEdit?.connection}
203 />
204 </>
205 );
206}