Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Delete lists #53

Merged
merged 5 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions src/api/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
updateDoc,
addDoc,
deleteDoc,
arrayRemove,
} from 'firebase/firestore';
import { useEffect, useState } from 'react';
import { db } from './config';
Expand Down Expand Up @@ -240,6 +241,91 @@ export async function deleteItem(listPath, id) {
}
}

export async function deleteList(collectionId, document, email) {
const listRef = doc(db, collectionId, document);
const userRef = doc(db, 'users', email);

try {
//check if list exists for debugging purposes
const docSnapshot = await getDoc(listRef);
if (!docSnapshot.exists()) {
console.log('Document does not exist:', listRef.path);
return;
} else {
console.log('Document exists:', listRef.path);
}
//actually delete the list
await deleteDoc(listRef);
console.log('Document deleted:', listRef.path);

//check if user list exists for debugging purposes
const docSnapshot2 = await getDoc(userRef);
if (!docSnapshot2.exists()) {
console.log('Document does not exist:', userRef.path);
return;
} else {
console.log('Document exists:', userRef.path);
}
//alert if user not found
const userDoc = await getDoc(userRef);
if (!userDoc.exists()) {
console.log('User document not found:', email);
return;
}
//show sharedLists contents before deleting ref
const sharedLists = userDoc.data().sharedLists;
console.log('Current sharedLists:', typeof sharedLists, sharedLists);
//actually delete ref from array
await updateDoc(userRef, {
sharedLists: arrayRemove(listRef),
});
console.log('User document updated');
} catch (error) {
console.error('Error deleting your list', error);
}
}

// export async function deleteCollection(listPath) {
// const collectionRef = collection(db, listPath);
// const query = collectionRef.orderBy('__name__').limit(500);
// console.log('delete collecton triggered');

// return new Promise((resolve, reject) => {
// console.log('inside promise');

// deleteQueryBatch(db, query, resolve).catch(reject);
// });
// }

// async function deleteQueryBatch(db, query, resolve) {
// const snapshot = await query.get();
// console.log('deletequery triggered');

// const batchSize = snapshot.size;
// if (batchSize === 0) {
// // When there are no documents left, we are done
// console.log('batch size 0');

// resolve();
// return;
// }

// // Delete documents in a batch
// const batch = db.batch();
// snapshot.docs.forEach((doc) => {
// console.log('deleted ', doc.ref);

// batch.delete(doc.ref);
// });
// await batch.commit();

// // Recurse on the next process tick, to avoid
// // exploding the stack.
// process.nextTick(() => {
// deleteQueryBatch(db, query, resolve);
// });
// }

export function comparePurchaseUrgency(arr) {
const groupedItems = {
Overdue: [],
Expand Down
40 changes: 37 additions & 3 deletions src/components/SingleList.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { deleteList } from '@/api';
import { getAuth } from 'firebase/auth';
import { useEffect, useState } from 'react';
import { FaShareNodes } from 'react-icons/fa6';
import { RiDeleteBin5Fill } from 'react-icons/ri';
import { useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';
export function SingleList({
name,
path,
listPath,
setListPath,
handleShareModalClick,
setSelectedItem,
}) {
const [collectionId, setCollectionId] = useState('');
const singleListPath = path.split('/')[0];
const email = getAuth().currentUser.email;

useEffect(() => {
setCollectionId(singleListPath);
}, []);

const navigate = useNavigate();

function handleClick() {
Expand All @@ -20,6 +33,18 @@ export function SingleList({
handleShareModalClick();
};

const handleDeleteClick = async (name) => {
await deleteList(collectionId, name, email);
console.log(listPath, name);

if (listPath.includes(name)) {
console.log();

setListPath('');
}
toast.success(`List ${name} was deleted`);
};

return (
<li className="flex flex-row align-middle justify-between px-2 py-3 rounded-[5px] text-[1.2em] space-x-5 w-full bg-white text-black">
<button
Expand All @@ -35,9 +60,18 @@ export function SingleList({
>
<FaShareNodes />
</button>
<button className="text-pink-500 hover:text-pink-600">
<RiDeleteBin5Fill />
</button>
{getAuth().currentUser.uid === singleListPath ? (
<button
onClick={() => handleDeleteClick(name)}
className="text-pink-500 hover:text-pink-600"
>
<RiDeleteBin5Fill />
</button>
) : (
<div className="text-gray-500">
<RiDeleteBin5Fill />
</div>
)}
</div>
</li>
);
Expand Down
2 changes: 2 additions & 0 deletions src/views/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export function Home({
handleShareModalClick,
}) {
const [selectedItem, setSelectedItem] = useState('');

return (
<div className="flex flex-col space-y-10 justify-center ">
<div className="flex flex-row justify-center">
Expand Down Expand Up @@ -40,6 +41,7 @@ export function Home({
key={index}
name={item.name}
path={item.path}
listPath={listPath}
setListPath={setListPath}
handleShareModalClick={handleShareModalClick}
setSelectedItem={setSelectedItem}
Expand Down
173 changes: 95 additions & 78 deletions src/views/List.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,87 +46,104 @@ export function List({ data, listPath, listName }) {
};

return (
<div className="flex flex-col space-y-10 justify-center items-center">
<div className="flex flex-row justify-center">
<div className="relative inline-block">
<h1 className="font-[montserrat] text-3xl font-bold text-gray">
<span className="relative inline-block">{listName}</span>
</h1>
<img
src="/img/underline.png"
alt="Description"
className="absolute bottom-[-12px] -right-3 w-14 h-3"
/>
</div>
</div>
<div className="flex flex-row justify-center items-center space-x-3 max-w-md w-full">
<SearchBar
setDisplayData={setDisplayData}
allData={allData}
setSearch={setSearch}
search={search}
/>
<Dialog open={isOpen} onOpenChange={handleAddModal}>
<DialogTrigger asChild>
<Button className="bg-transparen hover:bg-transparen p-0">
<SquarePlus className="h-7 w-7 text-pink dark:text-green transition-opacity hover:opacity-75" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add New Item</DialogTitle>
<DialogDescription>
Fill in the details of the item you want to add.
</DialogDescription>
</DialogHeader>
<AddItemForm
listPath={listPath}
data={data}
handleOpenModal={handleAddModal}
<>
{listPath === '' ? (
<div className="flex flex-col space-y-10 justify-center items-center">
<div className="relative inline-block">
<h1 className="font-[montserrat] text-3xl font-bold text-gray">
<span className="relative inline-block">No list selected</span>
</h1>
<img
src="/img/underline.png"
alt="Description"
className="absolute bottom-[-12px] -right-3 w-14 h-3"
/>
<DialogFooter className="sm:justify-start"></DialogFooter>
</DialogContent>
</Dialog>
</div>
<ul className="flex flex-col justify-center space-y-4 w-full max-w-md">
{displayData.map((item) => (
<ListItem
key={item.id}
name={item.name}
listPath={listPath}
id={item.id}
quantity={item.quantity}
isChecked={item.checked}
dateLastPurchased={item.dateLastPurchased}
totalPurchases={item.totalPurchases}
dayInterval={item.dayInterval}
dateCreated={item.dateCreated}
dateNextPurchased={item.dateNextPurchased}
indicator={item.indicator}
isOpen={openItemId === item.id}
handleOpenModal={handleEditModal}
/>
))}
</ul>
{displayData.length === 0 && search.length > 0 && (
<div className="flex flex-col items-center">
<p>No items found. Try searching for a different item!</p>
</div>
</div>
)}
{data.length === 0 && (
<div className="flex flex-col justify-center items-center gap-4 w-full mx-auto">
<p className="text-grey text-center">
Your list is empty. Start adding some items now!
</p>
<Button
className="bg-pink text-white rounded-xl w-full hover:bg-pink hover:bg-opacity-75 text-sm font-semibold max-w-[150px]"
id="addFirstItem"
onClick={() => setIsOpen((prev) => !prev)}
>
Add Item
</Button>
) : (
<div className="flex flex-col space-y-10 justify-center items-center">
<div className="flex flex-row justify-center">
<div className="relative inline-block">
<h1 className="font-[montserrat] text-3xl font-bold text-gray">
<span className="relative inline-block">{listName}</span>
</h1>
<img
src="/img/underline.png"
alt="Description"
className="absolute bottom-[-12px] -right-3 w-14 h-3"
/>
</div>
</div>
<div className="flex flex-row justify-center items-center space-x-3 max-w-md w-full">
<SearchBar
setDisplayData={setDisplayData}
allData={allData}
setSearch={setSearch}
search={search}
/>
<Dialog open={isOpen} onOpenChange={handleAddModal}>
<DialogTrigger asChild>
<Button className="bg-transparen hover:bg-transparen p-0">
<SquarePlus className="h-7 w-7 text-pink dark:text-green transition-opacity hover:opacity-75" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add New Item</DialogTitle>
<DialogDescription>
Fill in the details of the item you want to add.
</DialogDescription>
</DialogHeader>
<AddItemForm
listPath={listPath}
data={data}
handleOpenModal={handleAddModal}
/>
<DialogFooter className="sm:justify-start"></DialogFooter>
</DialogContent>
</Dialog>
</div>
<ul className="flex flex-col justify-center space-y-4 w-full max-w-md">
{displayData.map((item) => (
<ListItem
key={item.id}
name={item.name}
listPath={listPath}
id={item.id}
quantity={item.quantity}
isChecked={item.checked}
dateLastPurchased={item.dateLastPurchased}
totalPurchases={item.totalPurchases}
dayInterval={item.dayInterval}
dateCreated={item.dateCreated}
dateNextPurchased={item.dateNextPurchased}
indicator={item.indicator}
isOpen={openItemId === item.id}
handleOpenModal={handleEditModal}
/>
))}
</ul>
{displayData.length === 0 && search.length > 0 && (
<div className="flex flex-col items-center">
<p>No items found. Try searching for a different item!</p>
</div>
)}
{data.length === 0 && (
<div className="flex flex-col justify-center items-center gap-4 w-full mx-auto">
<p className="text-grey text-center">
Your list is empty. Start adding some items now!
</p>
<Button
className="bg-pink text-white rounded-xl w-full hover:bg-pink hover:bg-opacity-75 text-sm font-semibold max-w-[150px]"
id="addFirstItem"
onClick={() => setIsOpen((prev) => !prev)}
>
Add Item
</Button>
</div>
)}
</div>
)}
</div>
</>
);
}
Loading