This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

feat: url card, note card

+127 -21
+5 -8
src/webapp/app/(authenticated)/collections/[collectionId]/page.tsx
··· 4 4 import { useRouter, useParams } from 'next/navigation'; 5 5 import { getAccessToken } from '@/services/auth'; 6 6 import { ApiClient } from '@/api-client/ApiClient'; 7 - import { UrlCard } from '@/components/UrlCard'; 7 + 8 8 import type { GetCollectionPageResponse } from '@/api-client/types'; 9 9 import { 10 10 Button, ··· 17 17 Box, 18 18 SimpleGrid, 19 19 } from '@mantine/core'; 20 + import UrlCard from '@/features/cards/components/urlCard/UrlCard'; 20 21 21 22 export default function CollectionPage() { 22 23 const [collection, setCollection] = ··· 130 131 {collection.urlCards.map((card) => ( 131 132 <UrlCard 132 133 key={card.id} 133 - cardId={card.id} 134 + id={card.id} 134 135 url={card.url} 135 - title={card.cardContent.title} 136 - description={card.cardContent.description} 137 - author={card.cardContent.author} 138 - imageUrl={card.cardContent.thumbnailUrl} 139 - addedAt={card.createdAt} 140 - note={card.note?.text} 136 + cardContent={card.cardContent} 137 + note={card.note} 141 138 /> 142 139 ))} 143 140 </SimpleGrid>
+9 -9
src/webapp/app/(authenticated)/library/page.tsx
··· 4 4 import { useRouter } from 'next/navigation'; 5 5 import { ApiClient } from '@/api-client/ApiClient'; 6 6 import { getAccessToken } from '@/services/auth'; 7 - import { UrlCard } from '@/components/UrlCard'; 7 + import UrlCard from '@/features/cards/components/urlCard/UrlCard'; 8 8 import type { GetMyUrlCardsResponse } from '@/api-client/types'; 9 9 import { 10 10 Button, ··· 62 62 {cardsLoading ? ( 63 63 <Loader /> 64 64 ) : urlCards.length > 0 ? ( 65 - <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing={'md'}> 65 + <SimpleGrid 66 + cols={{ base: 1, xs: 2, sm: 3, lg: 4, xl: 5 }} 67 + spacing={'md'} 68 + > 66 69 {urlCards.map((card) => ( 67 70 <UrlCard 68 71 key={card.id} 69 - cardId={card.id} 72 + id={card.id} 70 73 url={card.url} 71 - title={card.cardContent.title} 72 - description={card.cardContent.description} 73 - author={card.cardContent.author} 74 - imageUrl={card.cardContent.thumbnailUrl} 75 - addedAt={card.createdAt} 76 - note={card.note?.text} 74 + cardContent={card.cardContent} 75 + note={card.note} 76 + collections={card.collections} 77 77 /> 78 78 ))} 79 79 </SimpleGrid>
+2 -2
src/webapp/components/FeedItem.tsx
··· 1 1 'use client'; 2 2 3 3 import { useRouter } from 'next/navigation'; 4 - import { UrlCard } from './UrlCard'; 4 + import { UrlCard } from './UrlCardOld'; 5 5 import type { FeedItem as FeedItemType } from '@/api-client/types'; 6 - import { Stack, Text, Group, Anchor, Box } from '@mantine/core'; 6 + import { Stack, Text, Anchor, Box } from '@mantine/core'; 7 7 8 8 interface FeedItemProps { 9 9 item: FeedItemType;
src/webapp/components/UrlCard.tsx src/webapp/components/UrlCardOld.tsx
+87
src/webapp/features/cards/components/urlCard/UrlCard.tsx
··· 1 + import { UrlCardView } from '@/api-client/types'; 2 + import { AddToCollectionModal } from '@/components/AddToCollectionModal'; 3 + import NoteCard from '@/features/notes/components/noteCard/NoteCard'; 4 + import { getDomain } from '@/lib/utils/link'; 5 + import { 6 + Card, 7 + Image, 8 + Text, 9 + Stack, 10 + Group, 11 + ActionIcon, 12 + Anchor, 13 + AspectRatio, 14 + } from '@mantine/core'; 15 + import { useDisclosure } from '@mantine/hooks'; 16 + import Link from 'next/link'; 17 + import { BiPlus } from 'react-icons/bi'; 18 + 19 + interface Props { 20 + size?: 'large' | 'compact' | 'small'; 21 + id: string; 22 + url: string; 23 + cardContent: UrlCardView['cardContent']; 24 + note?: UrlCardView['note']; 25 + collections?: UrlCardView['collections']; 26 + libraries?: UrlCardView['libraries']; 27 + } 28 + 29 + export default function UrlCard(props: Props) { 30 + const domain = getDomain(props.url); 31 + const [modalOpened, { open, close }] = useDisclosure(false); 32 + // TODO: add more sizes 33 + 34 + return ( 35 + <Stack component="article" gap={5} justify="stretch"> 36 + <Card withBorder radius={'lg'} p={'sm'} flex={1}> 37 + <Stack justify="space-between" gap={'sm'} flex={1}> 38 + <Group justify="space-between" align="start" wrap="nowrap" gap={'lg'}> 39 + <Stack gap={0}> 40 + <Anchor 41 + component={Link} 42 + href={props.url} 43 + target="_blank" 44 + c={'gray'} 45 + lineClamp={1} 46 + > 47 + {domain} 48 + </Anchor> 49 + {props.cardContent.title && ( 50 + <Text fw={500} lineClamp={1}> 51 + {props.cardContent.title} 52 + </Text> 53 + )} 54 + </Stack> 55 + {props.cardContent.thumbnailUrl && ( 56 + <AspectRatio ratio={1 / 1}> 57 + <Image 58 + src={props.cardContent.thumbnailUrl} 59 + alt={`${props.url} social preview image`} 60 + radius={'md'} 61 + w={75} 62 + h={75} 63 + /> 64 + </AspectRatio> 65 + )} 66 + </Group> 67 + <Group justify="space-between"> 68 + <ActionIcon 69 + variant="subtle" 70 + color={'gray'} 71 + radius={'xl'} 72 + onClick={open} 73 + > 74 + <BiPlus size={22} /> 75 + </ActionIcon> 76 + </Group> 77 + </Stack> 78 + </Card> 79 + {props.note && <NoteCard note={props.note.text} />} 80 + <AddToCollectionModal 81 + cardId={props.id} 82 + isOpen={modalOpened} 83 + onClose={close} 84 + /> 85 + </Stack> 86 + ); 87 + }
+4 -2
src/webapp/features/collections/components/collectionCard/CollectionCard.tsx
··· 38 38 > 39 39 <Stack justify="space-between" h={'100%'}> 40 40 <Stack gap={0}> 41 - <Text fw={600} fz={'lg'} lineClamp={1}> 41 + <Text fw={500} lineClamp={1}> 42 42 {collection.name} 43 43 </Text> 44 44 {collection.description && ( ··· 49 49 </Stack> 50 50 <Group justify="space-between"> 51 51 <Text c={'gray'}> 52 - {collection.cardCount} · {relativeUpdateDate} 52 + {collection.cardCount}{' '} 53 + {collection.cardCount === 1 ? 'card' : 'cards'} ·{' '} 54 + {relativeUpdateDate} 53 55 </Text> 54 56 <Anchor 55 57 component={Link}
+17
src/webapp/features/notes/components/noteCard/NoteCard.tsx
··· 1 + import { Card, Spoiler, Text } from '@mantine/core'; 2 + 3 + interface Props { 4 + note: string; 5 + } 6 + 7 + export default function NoteCard(props: Props) { 8 + return ( 9 + <Card bg={'#E5E8E7'} p={'sm'}> 10 + <Spoiler showLabel={'Read more'} hideLabel={'See less'} maxHeight={45}> 11 + <Text fz={'sm'} c={'#74867F'}> 12 + {props.note} 13 + </Text> 14 + </Spoiler> 15 + </Card> 16 + ); 17 + }
+3
src/webapp/lib/utils/link.ts
··· 1 + export const getDomain = (url: string) => { 2 + return new URL(url).hostname; 3 + };