Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function App() {
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="/list" element={<List data={data} />} />
<Route path="/add-item" element={<AddItem />} />
<Route path="/add-item" element={<AddItem listId={listToken} />} />
</Route>
</Routes>
</Router>
Expand Down
9 changes: 5 additions & 4 deletions src/api/firebase.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { collection, onSnapshot } from 'firebase/firestore';
import { addDoc, collection, onSnapshot } from 'firebase/firestore';
import { db } from './config';
import { getFutureDate } from '../utils';

Expand Down Expand Up @@ -53,17 +53,18 @@ export function getItemData(snapshot) {
*/
export async function addItem(listId, { itemName, daysUntilNextPurchase }) {
const listCollectionRef = collection(db, listId);
// TODO: Replace this call to console.log with the appropriate
// Firebase function, so this information is sent to your database!
return console.log(listCollectionRef, {
const data = await addDoc(listCollectionRef, {
dateCreated: new Date(),
// NOTE: This is null because the item has just been created.
// We'll use updateItem to put a Date here when the item is purchased!
dateLastPurchased: null,
dateNextPurchased: getFutureDate(daysUntilNextPurchase),
name: itemName,
totalPurchases: 0,
}).catch((err) => {
console.error(err);
});
return data;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Data in this case is a promise. How can you tell whether it was fulfilled or rejected?

}

export async function updateItem() {
Expand Down
115 changes: 113 additions & 2 deletions src/views/AddItem.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,114 @@
export function AddItem() {
return <p>Hello from the <code>/add-item</code> page!</p>
import { useEffect, useState } from 'react';
import { addItem } from '../api/firebase';

const timeframeToDays = {
Soon: 7,
'Kind of Soon': 14,
'Not Soon': 30,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This threw me off for a second. Is it possible to have them be consistent, maybe change 'Not Soon' to notSoon, kindOfSoon etc. And then update where this is being used in the form? I understand the default for one word keys is a string with no quotes (ex Soon). I tried adding quotes, but my linting is changing it back to this form as well.

Copy link
Collaborator

@mentalcaries mentalcaries Apr 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea @Yaosaur. Alternatively, what about swapping the keys and values?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored it out completely. It seemed like a good idea when we were writing our code but wasn't needed at all. 😅

};

export function AddItem({ listId }) {
const [timeframe, setTimeframe] = useState('Soon');
const [itemName, setItemName] = useState('');
const [message, setMessage] = useState(null);

useEffect(() => {
const timer = setTimeout(() => {
setMessage(null);
}, 3000);

return () => clearTimeout(timer);
}, [message]);

const onTimeChange = (e) => setTimeframe(e.target.value);
const onItemChange = (e) => setItemName(e.target.value);
const onFormSubmit = (e) => {
e.preventDefault();
// Make sure the user has entered an item name
if (!itemName) {
setMessage('Please enter an item name');
return;
}

const result = addItem(listId, {
itemName,
daysUntilNextPurchase: timeframeToDays[timeframe],
});
if (result) {
setMessage(`Added ${itemName} to your list.`);
setItemName('');
setTimeframe('Soon');
} else {
setMessage('Error adding item');
}
};

return (
<form onSubmit={onFormSubmit}>
<div
style={{
border: 'none',
padding: 0,
paddingBottom: '1.5rem',
display: 'flex',
flexDirection: 'column',
}}
>
<label htmlFor="itemName">Item name:</label>
<input
type="text"
id="itemName"
name="itemName"
value={itemName}
onChange={onItemChange}
></input>
</div>
<fieldset
style={{
border: 'none',
padding: 0,
display: 'grid',
gridTemplateColumns: '1fr 1fr',
}}
>
<label htmlFor="timeframe" style={{ gridColumn: 'span 2' }}>
How soon will you buy this again?
</label>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we replace with legend element for accessibility as per the wireframe requirement? See here: https://www.w3.org/WAI/tutorials/forms/grouping/#associating-related-controls-with-wai-aria

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, great suggestion!


<input
type="radio"
name="timeframe"
value="Soon"
id="soon"
checked={timeframe === 'Soon'}
onChange={onTimeChange}
/>

<label htmlFor="soon">Soon</label>

<input
type="radio"
name="timeframe"
value="Kind of Soon"
id="kindOfSoon"
checked={timeframe === 'Kind of Soon'}
onChange={onTimeChange}
/>

<label htmlFor="kindOfSoon">Kind of Soon</label>

<input
type="radio"
name="timeframe"
value="Not Soon"
id="notSoon"
checked={timeframe === 'Not Soon'}
onChange={onTimeChange}
/>
<label htmlFor="notSoon">Not Soon</label>
</fieldset>
<button type="submit">Add Item</button>
{message && <p>{message}</p>}
</form>
);
}