Something went wrong. Try again.
A social knowledge tool for research trails, built on ATProto semble.so
research-tool social-network tools-for-thought atproto
Something went wrong. Try again.
4.8 kB · 181 lines
TSX
at development
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182'use client';
import { useState, useEffect, useMemo, useCallback } from 'react';import { createClientTokenManager } from '@/services/auth';import { ApiClient } from '@/api-client/ApiClient';import { Button, Group, Modal, Stack, Text } from '@mantine/core';import { CollectionSelector } from './CollectionSelector';
interface Collection { id: string; name: string; description?: string; cardCount: number; authorId: string;}
interface AddToCollectionModalProps { cardId: string; isOpen: boolean; onClose: () => void; onSuccess?: () => void;}
export function AddToCollectionModal({ cardId, isOpen, onClose, onSuccess,}: AddToCollectionModalProps) { const [selectedCollectionIds, setSelectedCollectionIds] = useState<string[]>( [], ); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(''); const [card, setCard] = useState<any>(null); const [loading, setLoading] = useState(false);
// Create API client instance const apiClient = new ApiClient( process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000', createClientTokenManager(), );
// Get existing collections for this card const existingCollections = useMemo(() => { if (!card) return []; return card.collections || []; }, [card]);
const fetchCard = useCallback(async () => { // Create API client instance const apiClient = new ApiClient( process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000', createClientTokenManager(), );
try { setLoading(true); setError(''); const response = await apiClient.getUrlCardView(cardId); setCard(response); } catch (error: any) { console.error('Error fetching card:', error); setError(error.message || 'Failed to load card details'); } finally { setLoading(false); } }, [cardId]);
useEffect(() => { if (isOpen) { fetchCard(); } }, [isOpen, cardId, fetchCard]);
const handleSubmit = async () => { if (selectedCollectionIds.length === 0) { setError('Please select at least one collection'); return; }
setSubmitting(true); setError('');
try { // Create API client instance const apiClient = new ApiClient( process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000', createClientTokenManager(), );
// Add card to all selected collections in a single request await apiClient.addCardToCollection({ cardId, collectionIds: selectedCollectionIds, });
// Success onSuccess?.(); onClose(); setSelectedCollectionIds([]); } catch (error: any) { console.error('Error adding card to collections:', error); setError(error.message || 'Failed to add card to collections'); } finally { setSubmitting(false); } };
const handleClose = () => { if (!submitting) { onClose(); setSelectedCollectionIds([]); setError(''); } };
if (!isOpen) return null;
return ( <Modal opened={isOpen} onClose={handleClose} title="Add to Collections" centered size="md" > <Stack p="sm"> {loading ? ( <Text size="sm" c="dimmed" ta="center" py="md"> Loading card details... </Text> ) : error ? ( <Stack align="center"> <Text c="red">{error}</Text> <Button onClick={fetchCard} variant="outline" size="sm"> Try Again </Button> </Stack> ) : ( <> <CollectionSelector apiClient={apiClient} selectedCollectionIds={selectedCollectionIds} onSelectionChange={setSelectedCollectionIds} existingCollections={existingCollections} disabled={submitting} showCreateOption={true} placeholder="Search collections to add..." />
{error && ( <Text c="red" size="sm"> {error} </Text> )}
<Group gap={'xs'} grow> <Button onClick={handleSubmit} disabled={submitting || selectedCollectionIds.length === 0} loading={submitting} > {submitting ? 'Adding...' : `Add to ${selectedCollectionIds.length} Collection${selectedCollectionIds.length !== 1 && 's'}`} </Button> <Button variant="outline" onClick={handleClose} disabled={submitting} > Cancel </Button> </Group> </> )} </Stack> </Modal> );}