This repository has no description
4.4 kB
169 lines
1'use client';
2
3import { useState, useEffect, useMemo } from 'react';
4import { getAccessToken } from '@/services/auth';
5import { ApiClient } from '@/api-client/ApiClient';
6import { Button, Group, Modal, Stack, Text } from '@mantine/core';
7import { CollectionSelector } from './CollectionSelector';
8
9interface Collection {
10 id: string;
11 name: string;
12 description?: string;
13 cardCount: number;
14 authorId: string;
15}
16
17interface AddToCollectionModalProps {
18 cardId: string;
19 isOpen: boolean;
20 onClose: () => void;
21 onSuccess?: () => void;
22}
23
24export function AddToCollectionModal({
25 cardId,
26 isOpen,
27 onClose,
28 onSuccess,
29}: AddToCollectionModalProps) {
30 const [selectedCollectionIds, setSelectedCollectionIds] = useState<string[]>(
31 [],
32 );
33 const [submitting, setSubmitting] = useState(false);
34 const [error, setError] = useState('');
35 const [card, setCard] = useState<any>(null);
36 const [loading, setLoading] = useState(false);
37
38 // Create API client instance
39 const apiClient = new ApiClient(
40 process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3000',
41 () => getAccessToken(),
42 );
43
44 // Get existing collections for this card
45 const existingCollections = useMemo(() => {
46 if (!card) return [];
47 return card.collections || [];
48 }, [card]);
49
50 useEffect(() => {
51 if (isOpen) {
52 fetchCard();
53 }
54 }, [isOpen, cardId]);
55
56 const fetchCard = async () => {
57 try {
58 setLoading(true);
59 setError('');
60 const response = await apiClient.getUrlCardView(cardId);
61 setCard(response);
62 } catch (error: any) {
63 console.error('Error fetching card:', error);
64 setError(error.message || 'Failed to load card details');
65 } finally {
66 setLoading(false);
67 }
68 };
69
70 const handleSubmit = async () => {
71 if (selectedCollectionIds.length === 0) {
72 setError('Please select at least one collection');
73 return;
74 }
75
76 setSubmitting(true);
77 setError('');
78
79 try {
80 // Add card to all selected collections in a single request
81 await apiClient.addCardToCollection({
82 cardId,
83 collectionIds: selectedCollectionIds,
84 });
85
86 // Success
87 onSuccess?.();
88 onClose();
89 setSelectedCollectionIds([]);
90 } catch (error: any) {
91 console.error('Error adding card to collections:', error);
92 setError(error.message || 'Failed to add card to collections');
93 } finally {
94 setSubmitting(false);
95 }
96 };
97
98 const handleClose = () => {
99 if (!submitting) {
100 onClose();
101 setSelectedCollectionIds([]);
102 setError('');
103 }
104 };
105
106 if (!isOpen) return null;
107
108 return (
109 <Modal
110 opened={isOpen}
111 onClose={handleClose}
112 title="Add to Collections"
113 centered
114 size="md"
115 >
116 <Stack p="sm">
117 {loading ? (
118 <Text size="sm" c="dimmed" ta="center" py="md">
119 Loading card details...
120 </Text>
121 ) : error ? (
122 <Stack align="center">
123 <Text c="red">{error}</Text>
124 <Button onClick={fetchCard} variant="outline" size="sm">
125 Try Again
126 </Button>
127 </Stack>
128 ) : (
129 <>
130 <CollectionSelector
131 apiClient={apiClient}
132 selectedCollectionIds={selectedCollectionIds}
133 onSelectionChange={setSelectedCollectionIds}
134 existingCollections={existingCollections}
135 disabled={submitting}
136 showCreateOption={true}
137 placeholder="Search collections to add..."
138 />
139
140 {error && (
141 <Text c="red" size="sm">
142 {error}
143 </Text>
144 )}
145
146 <Group gap={'xs'} grow>
147 <Button
148 onClick={handleSubmit}
149 disabled={submitting || selectedCollectionIds.length === 0}
150 loading={submitting}
151 >
152 {submitting
153 ? 'Adding...'
154 : `Add to ${selectedCollectionIds.length} Collection${selectedCollectionIds.length !== 1 ? 's' : ''}`}
155 </Button>
156 <Button
157 variant="outline"
158 onClick={handleClose}
159 disabled={submitting}
160 >
161 Cancel
162 </Button>
163 </Group>
164 </>
165 )}
166 </Stack>
167 </Modal>
168 );
169}