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

Edit individual list items. #54

Merged
merged 8 commits into from
Oct 13, 2024
13 changes: 11 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Login from './views/Login';

export function App() {
const [isModalOpen, setIsModalOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);

/**
* This custom hook takes the path of a shopping list
* in our database and syncs it with localStorage for later use.
Expand All @@ -21,7 +23,7 @@ export function App() {
null,
);

const listName = listPath.split('/').pop();
const listName = listPath ? listPath.split('/').pop() : null;

/**
* This custom hook holds info about the current signed in user.
Expand Down Expand Up @@ -63,13 +65,20 @@ export function App() {
setListPath={setListPath}
isModalOpen={isModalOpen}
handleShareModalClick={handleShareModalClick}
setIsLoading={setIsLoading}
/>
}
/>
<Route
path="/list"
element={
<List data={data} listPath={listPath} listName={listName} />
<List
data={data}
listPath={listPath}
listName={listName}
isLoading={isLoading}
setIsLoading={setIsLoading}
/>
}
/>
</Route>
Expand Down
19 changes: 19 additions & 0 deletions src/api/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,25 @@ export async function updateItem(listPath, checked, itemData) {
}
}

export async function editItem(
listPath,
id,
{ itemName, itemQuantity, dateNextPurchased },
) {
const listCollectionRef = collection(db, listPath, 'items');
const itemRef = doc(listCollectionRef, id);

try {
await updateDoc(itemRef, {
name: itemName,
quantity: itemQuantity,
dateNextPurchased: dateNextPurchased,
});
} catch (error) {
console.error('There was an error editing the item state: ', error);
}
}

export async function deleteItem(listPath, id) {
const listCollectionRef = collection(db, listPath, 'items');
const itemRef = doc(listCollectionRef, id);
Expand Down
117 changes: 78 additions & 39 deletions src/components/ListItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
import { ONE_DAY_IN_MILLISECONDS } from '../utils/dates';
import toast from 'react-hot-toast';
import { Button } from './ui/button';
import { Trash2 } from 'lucide-react';
import { Trash2, Pencil } from 'lucide-react';
import { getIndicatorColor } from '../utils/helpers';
import {
AlertDialog,
Expand All @@ -16,6 +16,16 @@ import {
AlertDialogTitle,
AlertDialogTrigger,
} from './ui/alert-dialog';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import EditItemForm from './ManageListForms/EditItemForm';

export function ListItem({
listPath,
Expand All @@ -28,6 +38,9 @@ export function ListItem({
dayInterval,
dateCreated,
indicator,
isOpen,
handleOpenModal,
dateNextPurchased,
}) {
const [isAlertOpen, setIsAlertOpen] = useState(false);

Expand Down Expand Up @@ -81,7 +94,7 @@ export function ListItem({
>
<label
htmlFor={`${id}`}
className="capitalize text-sm hover:font-bold sm:text-lg"
className="capitalize text-sm sm:text-base md:text-lg hover:font-bold text-gray-800 dark:text-gray-300"
>
{name}
</label>
Expand All @@ -92,51 +105,77 @@ export function ListItem({
</div>
)}
</div>
<div className="flex items-center gap-1 sm:gap-2">
<div className="flex items-center gap-3">
<div
className={`${getIndicatorColor(indicator)} rounded-[3px] px-2 sm:rounded-[5px] sm:px-3`}
>
<p className="capitalize text-xs sm:text-sm text-black dark:text-gray-800">
{indicator}
</p>
</div>
<AlertDialog open={isAlertOpen} onOpenChange={setIsAlertOpen}>
<AlertDialogTrigger asChild>
<Button
className="bg-transparent hover:bg-transparent"
type="button"
id={id}
onClick={() => setIsAlertOpen(true)}
>
<Trash2 className="w-5 h-5 text-ruby-pink hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 sm:w-6 sm:h-6 md:w-7 md:h-7" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="p-6 sm:p-10">
<AlertDialogHeader>
<AlertDialogTitle className="text-sm text-slate-500 dark:text-slate-400 sm:text-lg">
Are you absolutely sure?
</AlertDialogTitle>
<AlertDialogDescription className="text-black">
This action cannot be undone. Do you really want to delete{' '}
{name}?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel
className="bg-white hover:bg-slate-100 px-6 border rounded-lg sm:px-8 sm:rounded-xl"
onClick={() => setIsAlertOpen(false)}
>
Cancel
</AlertDialogCancel>
<AlertDialogAction
className="bg-primary-pink hover:bg-opacity-75 rounded-lg sm:rounded-xl"
onClick={handleDelete}
<div className="flex gap-3 px-1">
<Dialog open={isOpen} onOpenChange={() => handleOpenModal(id)}>
<DialogTrigger asChild>
<Button className="bg-transparent hover:bg-transparent p-0">
<Pencil className="w-5 h-5 md:w-6 md:h-6 text-light-grey hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit {name}</DialogTitle>
<DialogDescription className="text-md md:text-lg">
Modify the details of the item you&apos;d like to edit.
</DialogDescription>
</DialogHeader>
<EditItemForm
listPath={listPath}
name={name}
id={id}
quantity={quantity}
dateNextPurchased={dateNextPurchased}
handleOpenModal={handleOpenModal}
/>
<DialogFooter className="sm:justify-start"></DialogFooter>
</DialogContent>
</Dialog>
<AlertDialog open={isAlertOpen} onOpenChange={setIsAlertOpen}>
<AlertDialogTrigger asChild>
<Button
className="bg-transparent hover:bg-transparent p-0"
type="button"
id={id}
onClick={() => setIsAlertOpen(true)}
>
Continue
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<Trash2 className="w-5 h-5 md:w-6 md:h-6 text-gray-600 hover:text-opacity-75 dark:text-emerald-500 dark:hover:text-opacity-80 transform hover:scale-110 transition-transform duration-150 sm:hover:scale-125" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="p-6 sm:p-10">
<AlertDialogHeader>
<AlertDialogTitle className="text-sm text-slate-800 dark:text-slate-400 sm:text-lg">
Are you absolutely sure?
</AlertDialogTitle>
<AlertDialogDescription className="text-slate-700">
This action cannot be undone. Do you really want to delete{' '}
{name}?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel
className="bg-white text-slate-700 hover:bg-slate-100 px-6 border rounded-lg sm:px-8 sm:rounded-xl"
onClick={() => setIsAlertOpen(false)}
>
Cancel
</AlertDialogCancel>
<AlertDialogAction
className="bg-primary-pink text-white hover:bg-opacity-90 px-6 border rounded-lg sm:px-8 sm:rounded-xl"
onClick={handleDelete}
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
</div>
</li>
);
Expand Down
19 changes: 14 additions & 5 deletions src/components/ManageListForms/AddItemForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ export default function AddItemForm({ listPath, data, handleOpenModal }) {
name="timeFrame"
className="border border-soon text-soon"
/>
<label htmlFor="soon" className="font-semibold text-sm">
<label
htmlFor="soon"
className="font-semibold text-sm cursor-pointer"
>
Soon
</label>
</div>
Expand All @@ -109,13 +112,19 @@ export default function AddItemForm({ listPath, data, handleOpenModal }) {
name="timeFrame"
className="border border-kind-of-soon text-kind-of-soon"
/>
<label htmlFor="kind-of-soon" className="font-semibold text-sm">
<label
htmlFor="kind-of-soon"
className="font-semibold text-sm cursor-pointer"
>
Kind of soon
</label>
</div>
<div className="flex flex-col items-center justify-center rounded-xl border border-light-pink gap-4 w-28 h-28 shadow-bottom-right transition-transform duration-200 ease-in-out transform active:scale-95">
<RadioGroupItem value="30" id="not-of-soon" name="timeFrame" />
<label htmlFor="not of soon" className="font-semibold text-sm">
<RadioGroupItem value="30" id="not-soon" name="timeFrame" />
<label
htmlFor="not-soon"
className="font-semibold text-sm cursor-pointer"
>
Not soon
</label>
</div>
Expand All @@ -141,7 +150,7 @@ export default function AddItemForm({ listPath, data, handleOpenModal }) {
<div className="flex w-full">
<Button
type="submit"
className="bg-primary-pink text-black rounded-xl w-full hover:bg-primary-pink hover:bg-opacity-80 text-sm p-6"
className="bg-primary-pink text-white rounded-xl w-full hover:bg-primary-pink hover:bg-opacity-90 text-sm p-6"
>
Add Item
</Button>
Expand Down
Loading
Loading