This repository has no description
semble
/
src
/
webapp
/
features
/
connections
/
components
/
addConnectionDrawer
/
SourceCardPreview.tsx
2.4 kB
93 lines
1'use client';
2
3import {
4 Anchor,
5 Card,
6 CloseButton,
7 Group,
8 Image,
9 Skeleton,
10 Stack,
11 Text,
12 Tooltip,
13} from '@mantine/core';
14import { useQuery } from '@tanstack/react-query';
15import { createSembleClient } from '@/services/client.apiClient';
16import { getDomain } from '@/lib/utils/link';
17
18function SourceCardPreviewSkeleton() {
19 return (
20 <Card withBorder component="article" p={'xs'} radius={'lg'}>
21 <Group gap="xs" wrap="nowrap">
22 <Skeleton width={42} height={42} radius={'md'} />
23 <Stack gap={0} style={{ flex: 1 }}>
24 <Skeleton height={21.5} width="80%" radius="sm" />
25 <Skeleton height={18.5} width="60%" radius="sm" mt={4} />
26 </Stack>
27 </Group>
28 </Card>
29 );
30}
31
32interface Props {
33 sourceUrl: string;
34 onRemove?: () => void;
35}
36
37export default function SourceCardPreview(props: Props) {
38 const { data, isLoading: isLoadingMetadata } = useQuery({
39 queryKey: ['url metadata', props.sourceUrl],
40 queryFn: async () => {
41 const client = createSembleClient();
42 return client.getUrlMetadata({ url: props.sourceUrl });
43 },
44 enabled: !!props.sourceUrl,
45 });
46
47 if (isLoadingMetadata) {
48 return <SourceCardPreviewSkeleton />;
49 }
50
51 return (
52 <Card withBorder component="article" p={'xs'} radius={'lg'}>
53 <Group gap="xs" wrap="nowrap">
54 {data?.metadata?.imageUrl && (
55 <Image
56 src={data.metadata.imageUrl}
57 alt={`${data.metadata.title} social preview image`}
58 radius={'md'}
59 w={42}
60 h={42}
61 style={{ flexShrink: 0 }}
62 />
63 )}
64 <Stack gap={0} style={{ flex: 1, minWidth: 0 }}>
65 <Text fw={500} lineClamp={1} c={'bright'}>
66 {data?.metadata?.title || props.sourceUrl}
67 </Text>
68 <Tooltip label={props.sourceUrl}>
69 <Anchor
70 href={props.sourceUrl}
71 target="_blank"
72 c={'gray'}
73 fz={'sm'}
74 lineClamp={1}
75 w="fit-content"
76 onClick={(e) => e.stopPropagation()}
77 >
78 {getDomain(props.sourceUrl)}
79 </Anchor>
80 </Tooltip>
81 </Stack>
82 {props.onRemove && (
83 <CloseButton
84 radius="xl"
85 size="md"
86 onClick={props.onRemove}
87 aria-label="Remove URL"
88 />
89 )}
90 </Group>
91 </Card>
92 );
93}