This repository has no description
3.1 kB
133 lines
1'use client';
2
3import { BiPlus, BiLinkExternal } from 'react-icons/bi';
4import { AddToCollectionModal } from './AddToCollectionModal';
5import {
6 ActionIcon,
7 Blockquote,
8 Box,
9 Card,
10 Group,
11 Image,
12 Stack,
13 Text,
14} from '@mantine/core';
15import { useDisclosure } from '@mantine/hooks';
16
17interface UrlCardProps {
18 cardId: string;
19 url: string;
20 title?: string;
21 description?: string;
22 author?: string;
23 siteName?: string;
24 imageUrl?: string;
25 addedAt: string;
26 note?: string;
27}
28
29export function UrlCard({
30 cardId,
31 url,
32 title,
33 description,
34 author,
35 siteName,
36 imageUrl,
37 addedAt,
38 note,
39}: UrlCardProps) {
40 const [modalOpened, { open, close }] = useDisclosure(false);
41
42 const formatDate = (dateString: string) => {
43 return new Date(dateString).toLocaleDateString('en-US', {
44 year: 'numeric',
45 month: 'short',
46 day: 'numeric',
47 });
48 };
49
50 const getDomain = (url: string) => {
51 try {
52 return new URL(url).hostname;
53 } catch {
54 return url;
55 }
56 };
57
58 const handleAddToCollectionSuccess = () => {
59 // Could show a toast notification here
60 console.log('Card added to collection(s) successfully');
61 };
62
63 return (
64 <Box>
65 <Card withBorder>
66 <Stack>
67 <Group justify="space-between" wrap="nowrap">
68 <Stack gap={0}>
69 <Text fw={600} lineClamp={1}>
70 {title || getDomain(url)}
71 </Text>
72 <Text fz={'sm'} fw={500} lineClamp={1} c={'gray'}>
73 {getDomain(url)} • {formatDate(addedAt)}
74 </Text>
75 </Stack>
76 <Group wrap="nowrap">
77 {imageUrl && (
78 <Image
79 src={imageUrl}
80 alt={title || 'Card image'}
81 w={64}
82 h={64}
83 radius={'md'}
84 />
85 )}
86 <Stack gap={'xs'}>
87 <ActionIcon
88 variant="transparent"
89 onClick={() => open()}
90 title="Add to collection"
91 >
92 <BiPlus />
93 </ActionIcon>
94 <ActionIcon
95 variant="transparent"
96 onClick={() => window.open(url, '_blank')}
97 title="Open link"
98 >
99 <BiLinkExternal />
100 </ActionIcon>
101 </Stack>
102 </Group>
103 </Group>
104
105 <Stack>
106 {description && (
107 <Text lineClamp={2} fz={'sm'}>
108 {description}
109 </Text>
110 )}
111 {author && (
112 <Text fw={500} fz={'xs'} c={'gray'}>
113 By {author}
114 </Text>
115 )}
116 {note && (
117 <Blockquote color="yellow" p={'xs'} fz={'sm'}>
118 {note}
119 </Blockquote>
120 )}
121 </Stack>
122 </Stack>
123 </Card>
124
125 <AddToCollectionModal
126 cardId={cardId}
127 isOpen={modalOpened}
128 onClose={close}
129 onSuccess={handleAddToCollectionSuccess}
130 />
131 </Box>
132 );
133}