Skip to content

Commit 83c0428

Browse files
authored
Merge pull request #53 from the-collab-lab/qg-feat-delete-list
Feat: Delete lists
2 parents 7eba74b + ed975e4 commit 83c0428

File tree

4 files changed

+284
-96
lines changed

4 files changed

+284
-96
lines changed

src/api/firebase.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
updateDoc,
99
addDoc,
1010
deleteDoc,
11+
arrayRemove,
1112
} from 'firebase/firestore';
1213
import { useEffect, useState } from 'react';
1314
import { db } from './config';
@@ -240,6 +241,91 @@ export async function deleteItem(listPath, id) {
240241
}
241242
}
242243

244+
export async function deleteList(collectionId, document, email) {
245+
const listRef = doc(db, collectionId, document);
246+
const userRef = doc(db, 'users', email);
247+
248+
try {
249+
//check if list exists for debugging purposes
250+
const docSnapshot = await getDoc(listRef);
251+
if (!docSnapshot.exists()) {
252+
console.log('Document does not exist:', listRef.path);
253+
return;
254+
} else {
255+
console.log('Document exists:', listRef.path);
256+
}
257+
//actually delete the list
258+
await deleteDoc(listRef);
259+
console.log('Document deleted:', listRef.path);
260+
261+
//check if user list exists for debugging purposes
262+
const docSnapshot2 = await getDoc(userRef);
263+
if (!docSnapshot2.exists()) {
264+
console.log('Document does not exist:', userRef.path);
265+
return;
266+
} else {
267+
console.log('Document exists:', userRef.path);
268+
}
269+
//alert if user not found
270+
const userDoc = await getDoc(userRef);
271+
if (!userDoc.exists()) {
272+
console.log('User document not found:', email);
273+
return;
274+
}
275+
//show sharedLists contents before deleting ref
276+
const sharedLists = userDoc.data().sharedLists;
277+
console.log('Current sharedLists:', typeof sharedLists, sharedLists);
278+
//actually delete ref from array
279+
await updateDoc(userRef, {
280+
sharedLists: arrayRemove(listRef),
281+
});
282+
console.log('User document updated');
283+
} catch (error) {
284+
console.error('Error deleting your list', error);
285+
}
286+
}
287+
288+
// export async function deleteCollection(listPath) {
289+
// const collectionRef = collection(db, listPath);
290+
// const query = collectionRef.orderBy('__name__').limit(500);
291+
// console.log('delete collecton triggered');
292+
293+
// return new Promise((resolve, reject) => {
294+
// console.log('inside promise');
295+
296+
// deleteQueryBatch(db, query, resolve).catch(reject);
297+
// });
298+
// }
299+
300+
// async function deleteQueryBatch(db, query, resolve) {
301+
// const snapshot = await query.get();
302+
// console.log('deletequery triggered');
303+
304+
// const batchSize = snapshot.size;
305+
// if (batchSize === 0) {
306+
// // When there are no documents left, we are done
307+
// console.log('batch size 0');
308+
309+
// resolve();
310+
// return;
311+
// }
312+
313+
// // Delete documents in a batch
314+
// const batch = db.batch();
315+
// snapshot.docs.forEach((doc) => {
316+
// console.log('deleted ', doc.ref);
317+
318+
// batch.delete(doc.ref);
319+
// });
320+
// await batch.commit();
321+
322+
// // Recurse on the next process tick, to avoid
323+
// // exploding the stack.
324+
// process.nextTick(() => {
325+
// deleteQueryBatch(db, query, resolve);
326+
// });
327+
// }
328+
243329
export function comparePurchaseUrgency(arr) {
244330
const groupedItems = {
245331
Overdue: [],

src/components/SingleList.jsx

Lines changed: 102 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,46 @@
1+
import { deleteList } from '@/api';
2+
import { getAuth } from 'firebase/auth';
3+
import { useEffect, useState } from 'react';
14
import { FaShareNodes } from 'react-icons/fa6';
2-
import { Trash2 } from 'lucide-react';
35
import { useNavigate } from 'react-router-dom';
6+
import toast from 'react-hot-toast';
7+
import {
8+
AlertDialog,
9+
AlertDialogAction,
10+
AlertDialogCancel,
11+
AlertDialogContent,
12+
AlertDialogDescription,
13+
AlertDialogFooter,
14+
AlertDialogHeader,
15+
AlertDialogTitle,
16+
AlertDialogTrigger,
17+
} from './ui/alert-dialog';
18+
import { Button } from './ui/button';
19+
import { Trash2 } from 'lucide-react';
20+
import {
21+
Tooltip,
22+
TooltipContent,
23+
TooltipProvider,
24+
TooltipTrigger,
25+
} from '@/components/ui/tooltip';
26+
427
export function SingleList({
528
name,
629
path,
30+
listPath,
731
setListPath,
832
handleShareModalClick,
933
setSelectedItem,
1034
}) {
35+
const [isAlertOpen, setIsAlertOpen] = useState(false);
36+
const [collectionId, setCollectionId] = useState('');
37+
const singleListPath = path.split('/')[0];
38+
const email = getAuth().currentUser.email;
39+
40+
useEffect(() => {
41+
setCollectionId(singleListPath);
42+
}, []);
43+
1144
const navigate = useNavigate();
1245

1346
function handleClick() {
@@ -20,6 +53,19 @@ export function SingleList({
2053
handleShareModalClick();
2154
};
2255

56+
const handleDeleteClick = async (name) => {
57+
await deleteList(collectionId, name, email);
58+
console.log(listPath, name);
59+
60+
if (listPath.includes(name)) {
61+
console.log();
62+
63+
setListPath('');
64+
}
65+
toast.success(`List ${name} was deleted`);
66+
setIsAlertOpen(false);
67+
};
68+
2369
return (
2470
<li className="flex flex-row align-middle justify-between pl-4 pr-4 py-[10px] rounded-[3px] text-[1em] space-x-3 w-full bg-white dark:bg-[#2f3031] text-black dark:text-gray-200 shadow-md shadow-slate-400 dark:shadow-gray-600 border border-gray-300 dark:border-gray-500 mt-2 sm:pl-6 sm:pr-6 sm:py-[14px] sm:rounded-[5px] sm:text-[1.2em] sm:space-x-5">
2571
<button
@@ -36,12 +82,61 @@ export function SingleList({
3682
>
3783
<FaShareNodes className="w-5 h-5 sm:w-6 sm:h-6" />
3884
</button>
39-
<button
40-
aria-label="Delete list"
41-
className="text-ruby-pink hover:text-ruby-pink hover:text-opacity-80 dark:text-emerald-500 dark:hover:text-emerald-300 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125"
42-
>
43-
<Trash2 className="w-5 h-5 sm:w-6 sm:h-6 md:w-7 md:h-7" />
44-
</button>
85+
{getAuth().currentUser.uid === singleListPath ? (
86+
<AlertDialog open={isAlertOpen} onOpenChange={setIsAlertOpen}>
87+
<AlertDialogTrigger asChild>
88+
<Button
89+
className="bg-transparent hover:bg-transparent"
90+
type="button"
91+
onClick={() => setIsAlertOpen(true)}
92+
>
93+
<Trash2 className="text-pink-500 hover:text-pink-600" />
94+
</Button>
95+
</AlertDialogTrigger>
96+
<AlertDialogContent>
97+
<AlertDialogHeader>
98+
<AlertDialogTitle className="text-sm text-slate-800 dark:text-slate-400 sm:text-lg">
99+
Are you absolutely sure?
100+
</AlertDialogTitle>
101+
<AlertDialogDescription className="text-slate-700">
102+
This will permanently delete your list. Do you really want to
103+
delete {name}?
104+
</AlertDialogDescription>
105+
</AlertDialogHeader>
106+
<AlertDialogFooter>
107+
<AlertDialogCancel
108+
className="bg-white text-slate-700 hover:bg-slate-100 px-6 border rounded-lg sm:px-8 sm:rounded-xl"
109+
onClick={() => setIsAlertOpen(false)}
110+
>
111+
Cancel
112+
</AlertDialogCancel>
113+
<AlertDialogAction
114+
className="bg-primary-pink text-white hover:bg-opacity-90 px-6 border rounded-lg sm:px-8 sm:rounded-xl"
115+
onClick={() => handleDeleteClick(name)}
116+
>
117+
Continue
118+
</AlertDialogAction>
119+
</AlertDialogFooter>
120+
</AlertDialogContent>
121+
</AlertDialog>
122+
) : (
123+
<TooltipProvider>
124+
<Tooltip delayDuration={100}>
125+
<TooltipTrigger asChild>
126+
<Button
127+
className="bg-transparent hover:bg-transparent"
128+
type="button"
129+
onClick={() => setIsAlertOpen(true)}
130+
>
131+
<Trash2 className="text-gray-500" />
132+
</Button>
133+
</TooltipTrigger>
134+
<TooltipContent>
135+
<p>You cannot delete a list you don&#39;t own!</p>
136+
</TooltipContent>
137+
</Tooltip>
138+
</TooltipProvider>
139+
)}
45140
</div>
46141
</li>
47142
);

src/views/Home.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export function Home({
1111
handleShareModalClick,
1212
}) {
1313
const [selectedItem, setSelectedItem] = useState('');
14+
1415
return (
1516
<div className="flex flex-col space-y-10 justify-center">
1617
<div className="flex flex-row justify-center">
@@ -49,6 +50,7 @@ export function Home({
4950
key={index}
5051
name={item.name}
5152
path={item.path}
53+
listPath={listPath}
5254
setListPath={setListPath}
5355
handleShareModalClick={handleShareModalClick}
5456
setSelectedItem={setSelectedItem}

0 commit comments

Comments
 (0)