Skip to content

Commit

Permalink
Merge pull request #48 from the-collab-lab/mf-add-item-dialog
Browse files Browse the repository at this point in the history
[MF] Add Item button that opens dialog on List.jsx WIP
  • Loading branch information
krsnamara committed Mar 25, 2024
2 parents 6311467 + 89b90a9 commit 2c6159d
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 47 deletions.
7 changes: 7 additions & 0 deletions public/img/add-green.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 17 additions & 5 deletions src/api/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export async function shareList(listPath, currentUserId, recipientEmail) {
*/
export async function addItem(listPath, { itemName, daysUntilNextPurchase }) {
if (itemName.trim() === '') {
return { success: false, error: 'Item cannot be empty.' };
return { success: false, error: 'Item cannot be empty.', status: 400 };
}

const listCollectionRef = collection(db, listPath, 'items');
Expand All @@ -220,7 +220,11 @@ export async function addItem(listPath, { itemName, daysUntilNextPurchase }) {
const itemExistsResult = itemExists(itemName, itemsSnapshot);

if (itemExistsResult) {
return { success: false, error: 'This item already exists in the list.' };
return {
success: false,
error: 'This item already exists in the list.',
status: 409,
};
}

try {
Expand All @@ -234,10 +238,18 @@ export async function addItem(listPath, { itemName, daysUntilNextPurchase }) {
totalPurchases: 0,
});

return { success: true, newDoc };
return {
success: true,
newDoc,
status: 201,
message: 'Item added successfully.',
};
} catch (err) {
console.error('Error adding new item:', err);
return { success: false };
return {
success: false,
status: 500,
error: 'Internal Server Error: Failed to add item.',
};
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/Dialog.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.Dialog {
--button-alignment: 'center';

border-radius: 8px;
border-radius: 20px;
max-width: min(68ch, 95vw);
padding: 0;
animation:
Expand Down
25 changes: 0 additions & 25 deletions src/components/ShareEmailInput.jsx

This file was deleted.

24 changes: 24 additions & 0 deletions src/views/List.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,27 @@
.List-items-section {
list-style-type: none;
}

.List-add-item-button {
border: none;
background: none;
z-index: 3;
position: fixed;
left: 50%;
top: 80%;
transform: translate(-50%, -50%);
cursor: pointer;
}

.List-add-item-button img {
width: 100%;
max-width: 100px;
}

@media (min-width: 600px) {
.List-add-item-button {
left: 75%;
top: 50%;
max-width: 200px;
}
}
167 changes: 151 additions & 16 deletions src/views/List.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { useState } from 'react';
import { ListItem } from '../components';
import { Link, Navigate } from 'react-router-dom';
import { comparePurchaseUrgency, shareList } from '../api';
import { addItem, comparePurchaseUrgency, shareList } from '../api';
import { ListItem } from '../components';
import { Dialog } from '../components/Dialog';
import ShareEmailInput from '../components/ShareEmailInput';

import './List.css';

export function List({ data, listPath, currentUserId }) {
const [searchString, setSearchString] = useState('');
const [recipientEmail, setRecipientEmail] = useState('');
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [isShareDialogOpen, setIsShareDialogOpen] = useState(false);
const [isAddItemDialogOpen, setIsAddItemDialogOpen] = useState(false);

const handleChange = (e) => {
setSearchString(e.target.value);
Expand Down Expand Up @@ -56,25 +56,77 @@ export function List({ data, listPath, currentUserId }) {
return <Navigate to="/" replace={true} />;
}

//** SHARE LIST HANDLERS ***//

function handleInviteChange(e) {
const { value } = e.target;
setRecipientEmail(value.toLowerCase());
}

async function handleShareList() {
setIsDialogOpen(true);
setIsShareDialogOpen(true);
setRecipientEmail('');
}

function handleCancelClick() {
setIsDialogOpen(false);
function handleShareCancelClick() {
setIsShareDialogOpen(false);
}

async function handleConfirmClick(e) {
async function handleShareConfirmClick(e) {
e.preventDefault();

let shareResult = await shareList(listPath, currentUserId, recipientEmail);
// provide an alert confirming that list was shared, or error
if (shareResult.status === 200) {
alert(shareResult.message);
setIsDialogOpen(false);
setIsShareDialogOpen(false);
} else {
alert(shareResult.message);
setRecipientEmail('');
setIsDialogOpen(true);
setIsShareDialogOpen(true);
}
}

//** ADD ITEM HANDLERS ***//

const INITIAL_DATA = {
itemName: '',
daysUntilNextPurchase: '7',
};

const [formData, setFormData] = useState(INITIAL_DATA);

function handleInputChange(e) {
const { name, value } = e.target;
setFormData((prevFormData) => ({
...prevFormData,
[name]: value,
}));
}

function handleAddItem() {
setIsAddItemDialogOpen(true);
// reset form data
setFormData({ itemName: '', daysUntilNextPurchase: '7' });
// set default radio button to 'soon'
document.getElementById('soon').checked = true;
}

function handleAddItemCancelClick() {
setIsAddItemDialogOpen(false);
}

async function handleAddItemConfirmClick(e) {
e.preventDefault();

let addItemResult = await addItem(listPath, formData);
// provide an alert confirming that list was shared, or error
if (addItemResult.status === 201) {
alert(addItemResult.message);
setIsAddItemDialogOpen(false);
} else {
alert(addItemResult.error);
setIsAddItemDialogOpen(true);
}
}

Expand All @@ -85,23 +137,31 @@ export function List({ data, listPath, currentUserId }) {
<button onClick={handleShareList}>Share List</button>
</div>
<Dialog
open={isDialogOpen}
onCancel={() => setIsDialogOpen(false)}
onSubmit={handleConfirmClick}
open={isShareDialogOpen}
onCancel={() => setIsShareDialogOpen(false)}
onSubmit={handleShareConfirmClick}
>
<h2>Who are you sharing this list with?</h2>
<div className="List-share-email-dialog-container">
<ShareEmailInput setRecipientEmail={setRecipientEmail} />
<label htmlFor="invite-to-list">
Enter email:
<input
type="email"
id="invite-to-list"
name="inviteToList"
onChange={handleInviteChange}
/>
</label>
<div className="Dialog--button-group">
<button
className="c-button c-button-cancel"
onClick={handleCancelClick}
onClick={handleShareCancelClick}
>
Cancel
</button>
<button
className="c-button c-button-confirm"
onClick={handleConfirmClick} // Remove arguments here
onClick={handleShareConfirmClick}
>
Confirm
</button>
Expand Down Expand Up @@ -160,6 +220,81 @@ export function List({ data, listPath, currentUserId }) {
</>
)}
</ul>
<button className="List-add-item-button" onClick={handleAddItem}>
<img src="/img/add-green.svg" alt="add item" />
</button>
<Dialog
open={isAddItemDialogOpen}
onCancel={() => setIsAddItemDialogOpen(false)}
onSubmit={handleAddItemConfirmClick}
>
<div className="List-modal-container">
<div className="List-modal-inner">
<div>Enter item</div>
<label htmlFor="itemName">
Item Name:
<input
type="text"
id="itemName"
name="itemName"
value={formData.itemName}
onChange={handleInputChange}
required
></input>
</label>
<br />
<p>Buy again?</p>
<label htmlFor="soon">
Soon:
<input
type="radio"
id="soon"
name="daysUntilNextPurchase"
value="7"
onChange={handleInputChange}
defaultChecked
></input>
</label>
<br />
<label htmlFor="kind-of-soon">
Kind of soon:
<input
type="radio"
id="kind-of-soon"
name="daysUntilNextPurchase"
value="14"
onChange={handleInputChange}
></input>
</label>
<br />
<label htmlFor="not-soon">
Not soon:
<input
type="radio"
id="not-soon"
name="daysUntilNextPurchase"
value="30"
onChange={handleInputChange}
></input>
</label>
<br />
<div className="Dialog--button-group">
<button
className="c-button c-button-cancel"
onClick={handleAddItemCancelClick}
>
Cancel
</button>
<button
className="c-button c-button-confirm"
onClick={handleAddItemConfirmClick}
>
Add Item
</button>
</div>
</div>
</div>
</Dialog>
</div>
);
}

0 comments on commit 2c6159d

Please sign in to comment.