This repository has no description
0

Configure Feed

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

semble / src / webapp / features / cards / components / addCardToModal / AddCardToModalContent.tsx
4.3 kB 141 lines
1'use client'; 2 3import type { Collection, UrlCard } from '@semble/types'; 4import { Stack } from '@mantine/core'; 5import { useState, useEffect } from 'react'; 6import CollectionSelector from '@/features/collections/components/collectionSelector/CollectionSelector'; 7import useGetCardFromMyLibrary from '@/features/cards/lib/queries/useGetCardFromMyLibrary'; 8import AddCardActions from '../addCardActions/AddCardActions'; 9 10interface Props { 11 onClose: () => void; 12 onSubmit: (data: { 13 isAddingNewCard: boolean; 14 cardData?: { 15 url: string; 16 note?: string; 17 collectionIds: string[]; 18 viaCardId?: string; 19 }; 20 updateData?: { 21 cardId: string; 22 note?: string; 23 addToCollectionIds?: string[]; 24 removeFromCollectionIds?: string[]; 25 addToLibrary?: boolean; 26 viaCardId?: string; 27 }; 28 }) => void; 29 url: string; 30 cardId?: string; 31 note?: string; 32 cardContent?: UrlCard['cardContent']; 33 viaCardId?: string; 34 isSaving: boolean; 35} 36 37export default function AddCardToModalContent(props: Props) { 38 const cardStatus = useGetCardFromMyLibrary({ url: props.url }); 39 const isMyCard = props?.cardId === cardStatus.data.card?.id; 40 const [note, setNote] = useState(isMyCard ? props.note : ''); 41 42 const collectionsWithCard = cardStatus.data.collections ?? []; 43 44 const [selectedCollections, setSelectedCollections] = 45 useState<Collection[]>(collectionsWithCard); 46 47 // Sync state with query data when it changes 48 useEffect(() => { 49 setSelectedCollections(cardStatus.data.collections ?? []); 50 }, [cardStatus.data.collections]); 51 52 const handleUpdateCard = (e: React.FormEvent) => { 53 e.preventDefault(); 54 55 const trimmedNote = note?.trimEnd() === '' ? undefined : note; 56 57 const addedCollections = selectedCollections.filter( 58 (c) => !collectionsWithCard.some((original) => original.id === c.id), 59 ); 60 61 const removedCollections = collectionsWithCard.filter( 62 (c) => !selectedCollections.some((selected) => selected.id === c.id), 63 ); 64 65 const hasNoteChanged = trimmedNote !== props.note; 66 const hasAdded = addedCollections.length > 0; 67 const hasRemoved = removedCollections.length > 0; 68 69 // no change, close modal 70 if (cardStatus.data.card && !hasNoteChanged && !hasAdded && !hasRemoved) { 71 props.onClose(); 72 return; 73 } 74 75 // card not yet in library, add it 76 if (!cardStatus.data.card) { 77 props.onSubmit({ 78 isAddingNewCard: true, 79 cardData: { 80 url: props.url, 81 note: trimmedNote, 82 collectionIds: selectedCollections.map((c) => c.id), 83 viaCardId: props.viaCardId, 84 }, 85 }); 86 return; 87 } 88 89 // card already in library, update associations instead 90 const updatedCardPayload: { 91 cardId: string; 92 note?: string; 93 addToCollectionIds?: string[]; 94 removeFromCollectionIds?: string[]; 95 addToLibrary?: boolean; 96 viaCardId?: string; 97 } = { cardId: cardStatus.data.card.id }; 98 99 if (hasNoteChanged) updatedCardPayload.note = trimmedNote; 100 if (hasAdded) 101 updatedCardPayload.addToCollectionIds = addedCollections.map((c) => c.id); 102 if (hasRemoved) 103 updatedCardPayload.removeFromCollectionIds = removedCollections.map( 104 (c) => c.id, 105 ); 106 107 // Track as a card save if we're adding collections or a note (indicates user is saving/organizing the card) 108 updatedCardPayload.addToLibrary = hasAdded || hasNoteChanged; 109 updatedCardPayload.viaCardId = props.viaCardId; 110 111 props.onSubmit({ 112 isAddingNewCard: false, 113 updateData: updatedCardPayload, 114 }); 115 }; 116 117 return ( 118 <Stack> 119 <AddCardActions 120 cardId={cardStatus.data.card?.id} 121 note={isMyCard ? note : cardStatus.data.card?.note?.text} 122 noteId={cardStatus.data.card?.note?.id} 123 onUpdateNote={setNote} 124 onClose={props.onClose} 125 /> 126 127 <CollectionSelector 128 isOpen={true} 129 onClose={props.onClose} 130 onCancel={() => { 131 props.onClose(); 132 setSelectedCollections(cardStatus.data.collections ?? []); 133 }} 134 onSave={handleUpdateCard} 135 isSaving={props.isSaving} 136 selectedCollections={selectedCollections} 137 onSelectedCollectionsChange={setSelectedCollections} 138 /> 139 </Stack> 140 ); 141}