This repository has no description
4.0 kB
129 lines
1'use client';
2
3import {
4 Anchor,
5 Avatar,
6 Card,
7 Group,
8 Menu,
9 ScrollArea,
10 Stack,
11 Text,
12} from '@mantine/core';
13import { FeedItem, Collection } from '@/api-client';
14import { Fragment } from 'react';
15import Link from 'next/link';
16import { getRelativeTime } from '@/lib/utils/time';
17import { getRecordKey } from '@/lib/utils/atproto';
18import { sanitizeText } from '@/lib/utils/text';
19import { useColorScheme } from '@mantine/hooks';
20import { BiCollection } from 'react-icons/bi';
21
22interface Props {
23 user: FeedItem['user'];
24 collections?: FeedItem['collections'];
25 createdAt: Date;
26}
27
28export default function FeedActivityStatus(props: Props) {
29 const colorScheme = useColorScheme();
30 const MAX_DISPLAYED = 2;
31 const time = getRelativeTime(props.createdAt.toString());
32 const relativeCreatedDate = time === 'just now' ? `Now` : `${time} ago`;
33
34 const renderActivityText = () => {
35 const collections = props.collections ?? [];
36 const displayedCollections = collections.slice(0, MAX_DISPLAYED);
37 const remainingCollections = collections.slice(
38 MAX_DISPLAYED,
39 collections.length,
40 );
41 const remainingCount = collections.length - MAX_DISPLAYED;
42
43 return (
44 <Text fw={500} c={'gray'}>
45 <Anchor
46 component={Link}
47 href={`/profile/${props.user.handle}`}
48 c="dark"
49 fw={600}
50 >
51 {sanitizeText(props.user.name)}
52 </Anchor>{' '}
53 {collections.length === 0 ? (
54 'added to library'
55 ) : (
56 <Fragment>
57 added to{' '}
58 {displayedCollections.map(
59 (collection: Collection, index: number) => (
60 <span key={collection.id}>
61 <Anchor
62 component={Link}
63 href={`/profile/${collection.author.handle}/collections/${getRecordKey(collection.uri!)}`}
64 c="grape"
65 fw={500}
66 >
67 {collection.name}
68 </Anchor>
69 {index < displayedCollections.length - 1 ? ', ' : ''}
70 </span>
71 ),
72 )}
73 {remainingCount > 0 && ' and '}
74 {remainingCount > 0 && (
75 <Menu shadow="sm">
76 <Menu.Target>
77 <Text
78 fw={600}
79 c={'blue'}
80 style={{ cursor: 'pointer', userSelect: 'none' }}
81 span
82 >
83 {remainingCount} other collection
84 {remainingCount > 1 ? 's' : ''}
85 </Text>
86 </Menu.Target>
87 <Menu.Dropdown maw={380}>
88 <ScrollArea.Autosize mah={150} type="auto">
89 {remainingCollections.map((c) => (
90 <Menu.Item
91 key={c.id}
92 component={Link}
93 href={`/profile/${c.author.handle}/collections/${getRecordKey(c.uri!)}`}
94 target="_blank"
95 c="blue"
96 fw={600}
97 >
98 {c.name}
99 </Menu.Item>
100 ))}
101 </ScrollArea.Autosize>
102 </Menu.Dropdown>
103 </Menu>
104 )}
105 </Fragment>
106 )}
107 <Text fz={'sm'} fw={600} c={'gray'} span display={'block'}>
108 {relativeCreatedDate}
109 </Text>
110 </Text>
111 );
112 };
113
114 return (
115 <Card p={0} bg={colorScheme === 'dark' ? 'dark.4' : 'gray.1'} radius={'lg'}>
116 <Stack gap={'xs'}>
117 <Group gap={'xs'} wrap="nowrap" align="center" p={'xs'}>
118 <Avatar
119 component={Link}
120 href={`/profile/${props.user.handle}`}
121 src={props.user.avatarUrl}
122 alt={`${props.user.name}'s' avatar`}
123 />
124 {renderActivityText()}
125 </Group>
126 </Stack>
127 </Card>
128 );
129}